diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2016-07-22 18:15:38 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2016-07-22 18:15:38 +0000 |
commit | 22b955cca564a9a3a5b8c9d9dd1e295b7943c128 (patch) | |
tree | abdbd898676e1f853fca2d7e031d105d7ebcf676 /libgo/go/crypto | |
parent | 9d04a3af4c6491536badf6bde9707c907e4d196b (diff) | |
download | gcc-22b955cca564a9a3a5b8c9d9dd1e295b7943c128.zip gcc-22b955cca564a9a3a5b8c9d9dd1e295b7943c128.tar.gz gcc-22b955cca564a9a3a5b8c9d9dd1e295b7943c128.tar.bz2 |
libgo: update to go1.7rc3
Reviewed-on: https://go-review.googlesource.com/25150
From-SVN: r238662
Diffstat (limited to 'libgo/go/crypto')
106 files changed, 3866 insertions, 887 deletions
diff --git a/libgo/go/crypto/aes/aes_gcm.go b/libgo/go/crypto/aes/aes_gcm.go index 1377578..a894a68 100644 --- a/libgo/go/crypto/aes/aes_gcm.go +++ b/libgo/go/crypto/aes/aes_gcm.go @@ -45,9 +45,12 @@ var errOpen = errors.New("cipher: message authentication failed") // will use the optimised implementation in this file when possible. Instances // of this type only exist when hasGCMAsm returns true. type aesCipherGCM struct { - aesCipher + aesCipherAsm } +// Assert that aesCipherGCM implements the gcmAble interface. +var _ gcmAble = (*aesCipherGCM)(nil) + // NewGCM returns the AES cipher wrapped in Galois Counter Mode. This is only // called by crypto/cipher.NewGCM via the gcmAble interface. func (c *aesCipherGCM) NewGCM(nonceSize int) (cipher.AEAD, error) { diff --git a/libgo/go/crypto/aes/aes_test.go b/libgo/go/crypto/aes/aes_test.go index 3631809..2814496 100644 --- a/libgo/go/crypto/aes/aes_test.go +++ b/libgo/go/crypto/aes/aes_test.go @@ -280,42 +280,6 @@ var encryptTests = []CryptTest{ }, } -// Test encryptBlock against FIPS 197 examples. -func TestEncryptBlock(t *testing.T) { - for i, tt := range encryptTests { - n := len(tt.key) + 28 - enc := make([]uint32, n) - dec := make([]uint32, n) - expandKey(tt.key, enc, dec) - out := make([]byte, len(tt.in)) - encryptBlock(enc, out, tt.in) - for j, v := range out { - if v != tt.out[j] { - t.Errorf("encryptBlock %d: out[%d] = %#x, want %#x", i, j, v, tt.out[j]) - break - } - } - } -} - -// Test decryptBlock against FIPS 197 examples. -func TestDecryptBlock(t *testing.T) { - for i, tt := range encryptTests { - n := len(tt.key) + 28 - enc := make([]uint32, n) - dec := make([]uint32, n) - expandKey(tt.key, enc, dec) - plain := make([]byte, len(tt.in)) - decryptBlock(dec, plain, tt.out) - for j, v := range plain { - if v != tt.in[j] { - t.Errorf("decryptBlock %d: plain[%d] = %#x, want %#x", i, j, v, tt.in[j]) - break - } - } - } -} - // Test Cipher Encrypt method against FIPS 197 examples. func TestCipherEncrypt(t *testing.T) { for i, tt := range encryptTests { diff --git a/libgo/go/crypto/aes/block.go b/libgo/go/crypto/aes/block.go index 57a7e9e..41ea9cf 100644 --- a/libgo/go/crypto/aes/block.go +++ b/libgo/go/crypto/aes/block.go @@ -137,7 +137,7 @@ func subw(w uint32) uint32 { // Rotate func rotw(w uint32) uint32 { return w<<8 | w>>24 } -// Key expansion algorithm. See FIPS-197, Figure 11. +// Key expansion algorithm. See FIPS-197, Figure 11. // Their rcon[i] is our powx[i-1] << 24. func expandKeyGo(key []byte, enc, dec []uint32) { // Encryption key setup. diff --git a/libgo/go/crypto/aes/cbc_s390x.go b/libgo/go/crypto/aes/cbc_s390x.go new file mode 100644 index 0000000..427b30b --- /dev/null +++ b/libgo/go/crypto/aes/cbc_s390x.go @@ -0,0 +1,59 @@ +// Copyright 2016 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 aes + +import ( + "crypto/cipher" +) + +// Assert that aesCipherAsm implements the cbcEncAble and cbcDecAble interfaces. +var _ cbcEncAble = (*aesCipherAsm)(nil) +var _ cbcDecAble = (*aesCipherAsm)(nil) + +type cbc struct { + b *aesCipherAsm + c code + iv [BlockSize]byte +} + +func (b *aesCipherAsm) NewCBCEncrypter(iv []byte) cipher.BlockMode { + var c cbc + c.b = b + c.c = b.function + copy(c.iv[:], iv) + return &c +} + +func (b *aesCipherAsm) NewCBCDecrypter(iv []byte) cipher.BlockMode { + var c cbc + c.b = b + c.c = b.function + 128 // decrypt function code is encrypt + 128 + copy(c.iv[:], iv) + return &c +} + +func (x *cbc) BlockSize() int { return BlockSize } + +// cryptBlocksChain invokes the cipher message with chaining (KMC) instruction +// with the given function code. The length must be a multiple of BlockSize (16). +//go:noescape +func cryptBlocksChain(c code, iv, key, dst, src *byte, length int) + +func (x *cbc) CryptBlocks(dst, src []byte) { + if len(src)%BlockSize != 0 { + panic("crypto/cipher: input not full blocks") + } + if len(dst) < len(src) { + panic("crypto/cipher: output smaller than input") + } + cryptBlocksChain(x.c, &x.iv[0], &x.b.key[0], &dst[0], &src[0], len(src)) +} + +func (x *cbc) SetIV(iv []byte) { + if len(iv) != BlockSize { + panic("cipher: incorrect length IV") + } + copy(x.iv[:], iv) +} diff --git a/libgo/go/crypto/aes/cipher.go b/libgo/go/crypto/aes/cipher.go index 04d2be1..c5a8e91 100644 --- a/libgo/go/crypto/aes/cipher.go +++ b/libgo/go/crypto/aes/cipher.go @@ -36,15 +36,15 @@ func NewCipher(key []byte) (cipher.Block, error) { case 16, 24, 32: break } + return newCipher(key) +} - n := k + 28 +// newCipherGeneric creates and returns a new cipher.Block +// implemented in pure Go. +func newCipherGeneric(key []byte) (cipher.Block, error) { + n := len(key) + 28 c := aesCipher{make([]uint32, n), make([]uint32, n)} - expandKey(key, c.enc, c.dec) - - if hasGCMAsm() { - return &aesCipherGCM{c}, nil - } - + expandKeyGo(key, c.enc, c.dec) return &c, nil } @@ -57,7 +57,7 @@ func (c *aesCipher) Encrypt(dst, src []byte) { if len(dst) < BlockSize { panic("crypto/aes: output not full block") } - encryptBlock(c.enc, dst, src) + encryptBlockGo(c.enc, dst, src) } func (c *aesCipher) Decrypt(dst, src []byte) { @@ -67,5 +67,5 @@ func (c *aesCipher) Decrypt(dst, src []byte) { if len(dst) < BlockSize { panic("crypto/aes: output not full block") } - decryptBlock(c.dec, dst, src) + decryptBlockGo(c.dec, dst, src) } diff --git a/libgo/go/crypto/aes/cipher_amd64.go b/libgo/go/crypto/aes/cipher_amd64.go new file mode 100644 index 0000000..b33c8ff --- /dev/null +++ b/libgo/go/crypto/aes/cipher_amd64.go @@ -0,0 +1,83 @@ +// 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 aes + +import ( + "crypto/cipher" +) + +// defined in asm_amd64.s +func hasAsm() bool +func encryptBlockAsm(nr int, xk *uint32, dst, src *byte) +func decryptBlockAsm(nr int, xk *uint32, dst, src *byte) +func expandKeyAsm(nr int, key *byte, enc *uint32, dec *uint32) + +type aesCipherAsm struct { + aesCipher +} + +var useAsm = hasAsm() + +func newCipher(key []byte) (cipher.Block, error) { + if !useAsm { + return newCipherGeneric(key) + } + n := len(key) + 28 + c := aesCipherAsm{aesCipher{make([]uint32, n), make([]uint32, n)}} + rounds := 10 + switch len(key) { + case 128 / 8: + rounds = 10 + case 192 / 8: + rounds = 12 + case 256 / 8: + rounds = 14 + } + expandKeyAsm(rounds, &key[0], &c.enc[0], &c.dec[0]) + if hasGCMAsm() { + return &aesCipherGCM{c}, nil + } + + return &c, nil +} + +func (c *aesCipherAsm) BlockSize() int { return BlockSize } + +func (c *aesCipherAsm) Encrypt(dst, src []byte) { + if len(src) < BlockSize { + panic("crypto/aes: input not full block") + } + if len(dst) < BlockSize { + panic("crypto/aes: output not full block") + } + encryptBlockAsm(len(c.enc)/4-1, &c.enc[0], &dst[0], &src[0]) +} + +func (c *aesCipherAsm) Decrypt(dst, src []byte) { + if len(src) < BlockSize { + panic("crypto/aes: input not full block") + } + if len(dst) < BlockSize { + panic("crypto/aes: output not full block") + } + decryptBlockAsm(len(c.dec)/4-1, &c.dec[0], &dst[0], &src[0]) +} + +// expandKey is used by BenchmarkExpand to ensure that the asm implementation +// of key expansion is used for the benchmark when it is available. +func expandKey(key []byte, enc, dec []uint32) { + if useAsm { + rounds := 10 // rounds needed for AES128 + switch len(key) { + case 192 / 8: + rounds = 12 + case 256 / 8: + rounds = 14 + } + expandKeyAsm(rounds, &key[0], &enc[0], &dec[0]) + } else { + expandKeyGo(key, enc, dec) + } +} diff --git a/libgo/go/crypto/aes/cipher_asm.go b/libgo/go/crypto/aes/cipher_asm.go deleted file mode 100644 index 964eaaa..0000000 --- a/libgo/go/crypto/aes/cipher_asm.go +++ /dev/null @@ -1,48 +0,0 @@ -// 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. - -// +build amd64 - -package aes - -// defined in asm_$GOARCH.s -func hasAsm() bool -func encryptBlockAsm(nr int, xk *uint32, dst, src *byte) -func decryptBlockAsm(nr int, xk *uint32, dst, src *byte) -func expandKeyAsm(nr int, key *byte, enc *uint32, dec *uint32) - -var useAsm = hasAsm() - -func encryptBlock(xk []uint32, dst, src []byte) { - if useAsm { - encryptBlockAsm(len(xk)/4-1, &xk[0], &dst[0], &src[0]) - } else { - encryptBlockGo(xk, dst, src) - } -} - -func decryptBlock(xk []uint32, dst, src []byte) { - if useAsm { - decryptBlockAsm(len(xk)/4-1, &xk[0], &dst[0], &src[0]) - } else { - decryptBlockGo(xk, dst, src) - } -} - -func expandKey(key []byte, enc, dec []uint32) { - if useAsm { - rounds := 10 - switch len(key) { - case 128 / 8: - rounds = 10 - case 192 / 8: - rounds = 12 - case 256 / 8: - rounds = 14 - } - expandKeyAsm(rounds, &key[0], &enc[0], &dec[0]) - } else { - expandKeyGo(key, enc, dec) - } -} diff --git a/libgo/go/crypto/aes/cipher_generic.go b/libgo/go/crypto/aes/cipher_generic.go index 32b2b3c..f807034 100644 --- a/libgo/go/crypto/aes/cipher_generic.go +++ b/libgo/go/crypto/aes/cipher_generic.go @@ -2,26 +2,25 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !amd64 +// +build !amd64,!s390x package aes -func encryptBlock(xk []uint32, dst, src []byte) { - encryptBlockGo(xk, dst, src) -} +import ( + "crypto/cipher" +) -func decryptBlock(xk []uint32, dst, src []byte) { - decryptBlockGo(xk, dst, src) +// newCipher calls the newCipherGeneric function +// directly. Platforms with hardware accelerated +// implementations of AES should implement their +// own version of newCipher (which may then call +// newCipherGeneric if needed). +func newCipher(key []byte) (cipher.Block, error) { + return newCipherGeneric(key) } +// expandKey is used by BenchmarkExpand and should +// call an assembly implementation if one is available. func expandKey(key []byte, enc, dec []uint32) { expandKeyGo(key, enc, dec) } - -func hasGCMAsm() bool { - return false -} - -type aesCipherGCM struct { - aesCipher -} diff --git a/libgo/go/crypto/aes/cipher_s390x.go b/libgo/go/crypto/aes/cipher_s390x.go new file mode 100644 index 0000000..bec5933 --- /dev/null +++ b/libgo/go/crypto/aes/cipher_s390x.go @@ -0,0 +1,90 @@ +// Copyright 2016 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 aes + +import ( + "crypto/cipher" +) + +type code int + +// Function codes for the cipher message family of instructions. +const ( + aes128 code = 18 + aes192 = 19 + aes256 = 20 +) + +type aesCipherAsm struct { + function code // code for cipher message instruction + key []byte // key (128, 192 or 256 bytes) + storage [256]byte // array backing key slice +} + +// hasAsm reports whether the AES-128, AES-192 and AES-256 +// cipher message (KM) function codes are supported. +// Note: this function call is expensive. +func hasAsm() bool + +// cryptBlocks invokes the cipher message (KM) instruction with +// the given function code. This is equivalent to AES in ECB +// mode. The length must be a multiple of BlockSize (16). +//go:noesape +func cryptBlocks(c code, key, dst, src *byte, length int) + +var useAsm = hasAsm() + +func newCipher(key []byte) (cipher.Block, error) { + if !useAsm { + return newCipherGeneric(key) + } + + var function code + switch len(key) { + case 128 / 8: + function = aes128 + case 192 / 8: + function = aes192 + case 256 / 8: + function = aes256 + default: + return nil, KeySizeError(len(key)) + } + + var c aesCipherAsm + c.function = function + c.key = c.storage[:len(key)] + copy(c.key, key) + return &c, nil +} + +func (c *aesCipherAsm) BlockSize() int { return BlockSize } + +func (c *aesCipherAsm) Encrypt(dst, src []byte) { + if len(src) < BlockSize { + panic("crypto/aes: input not full block") + } + if len(dst) < BlockSize { + panic("crypto/aes: output not full block") + } + cryptBlocks(c.function, &c.key[0], &dst[0], &src[0], BlockSize) +} + +func (c *aesCipherAsm) Decrypt(dst, src []byte) { + if len(src) < BlockSize { + panic("crypto/aes: input not full block") + } + if len(dst) < BlockSize { + panic("crypto/aes: output not full block") + } + // The decrypt function code is equal to the function code + 128. + cryptBlocks(c.function+128, &c.key[0], &dst[0], &src[0], BlockSize) +} + +// expandKey is used by BenchmarkExpand. cipher message (KM) does not need key +// expansion so there is no assembly equivalent. +func expandKey(key []byte, enc, dec []uint32) { + expandKeyGo(key, enc, dec) +} diff --git a/libgo/go/crypto/aes/ctr_s390x.go b/libgo/go/crypto/aes/ctr_s390x.go new file mode 100644 index 0000000..94dea5c --- /dev/null +++ b/libgo/go/crypto/aes/ctr_s390x.go @@ -0,0 +1,76 @@ +// Copyright 2016 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 aes + +import ( + "crypto/cipher" + "unsafe" +) + +// Assert that aesCipherAsm implements the ctrAble interface. +var _ ctrAble = (*aesCipherAsm)(nil) + +// xorBytes xors the contents of a and b and places the resulting values into +// dst. If a and b are not the same length then the number of bytes processed +// will be equal to the length of shorter of the two. Returns the number +// of bytes processed. +//go:noescape +func xorBytes(dst, a, b []byte) int + +// streamBufferSize is the number of bytes of encrypted counter values to cache. +const streamBufferSize = 32 * BlockSize + +type aesctr struct { + block *aesCipherAsm // block cipher + ctr [2]uint64 // next value of the counter (big endian) + buffer []byte // buffer for the encrypted counter values + storage [streamBufferSize]byte // array backing buffer slice +} + +// NewCTR returns a Stream which encrypts/decrypts using the AES block +// cipher in counter mode. The length of iv must be the same as BlockSize. +func (c *aesCipherAsm) NewCTR(iv []byte) cipher.Stream { + if len(iv) != BlockSize { + panic("cipher.NewCTR: IV length must equal block size") + } + var ac aesctr + ac.block = c + ac.ctr[0] = *(*uint64)(unsafe.Pointer((&iv[0]))) // high bits + ac.ctr[1] = *(*uint64)(unsafe.Pointer((&iv[8]))) // low bits + ac.buffer = ac.storage[:0] + return &ac +} + +func (c *aesctr) refill() { + // Fill up the buffer with an incrementing count. + c.buffer = c.storage[:streamBufferSize] + c0, c1 := c.ctr[0], c.ctr[1] + for i := 0; i < streamBufferSize; i += BlockSize { + b0 := (*uint64)(unsafe.Pointer(&c.buffer[i])) + b1 := (*uint64)(unsafe.Pointer(&c.buffer[i+BlockSize/2])) + *b0, *b1 = c0, c1 + // Increment in big endian: c0 is high, c1 is low. + c1++ + if c1 == 0 { + // add carry + c0++ + } + } + c.ctr[0], c.ctr[1] = c0, c1 + // Encrypt the buffer using AES in ECB mode. + cryptBlocks(c.block.function, &c.block.key[0], &c.buffer[0], &c.buffer[0], streamBufferSize) +} + +func (c *aesctr) XORKeyStream(dst, src []byte) { + for len(src) > 0 { + if len(c.buffer) == 0 { + c.refill() + } + n := xorBytes(dst, src, c.buffer) + c.buffer = c.buffer[n:] + src = src[n:] + dst = dst[n:] + } +} diff --git a/libgo/go/crypto/aes/modes.go b/libgo/go/crypto/aes/modes.go new file mode 100644 index 0000000..1623fc1 --- /dev/null +++ b/libgo/go/crypto/aes/modes.go @@ -0,0 +1,37 @@ +// Copyright 2016 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 aes + +import ( + "crypto/cipher" +) + +// gcmAble is implemented by cipher.Blocks that can provide an optimized +// implementation of GCM through the AEAD interface. +// See crypto/cipher/gcm.go. +type gcmAble interface { + NewGCM(size int) (cipher.AEAD, error) +} + +// cbcEncAble is implemented by cipher.Blocks that can provide an optimized +// implementation of CBC encryption through the cipher.BlockMode interface. +// See crypto/cipher/cbc.go. +type cbcEncAble interface { + NewCBCEncrypter(iv []byte) cipher.BlockMode +} + +// cbcDecAble is implemented by cipher.Blocks that can provide an optimized +// implementation of CBC decryption through the cipher.BlockMode interface. +// See crypto/cipher/cbc.go. +type cbcDecAble interface { + NewCBCDecrypter(iv []byte) cipher.BlockMode +} + +// ctrAble is implemented by cipher.Blocks that can provide an optimized +// implementation of CTR through the cipher.Stream interface. +// See crypto/cipher/ctr.go. +type ctrAble interface { + NewCTR(iv []byte) cipher.Stream +} diff --git a/libgo/go/crypto/aes/modes_test.go b/libgo/go/crypto/aes/modes_test.go new file mode 100644 index 0000000..8c2e5f0 --- /dev/null +++ b/libgo/go/crypto/aes/modes_test.go @@ -0,0 +1,112 @@ +// Copyright 2016 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 aes + +import ( + "crypto/cipher" + "testing" +) + +// Check that the optimized implementations of cipher modes will +// be picked up correctly. + +// testInterface can be asserted to check that a type originates +// from this test group. +type testInterface interface { + InAESPackage() bool +} + +// testBlock implements the cipher.Block interface and any *Able +// interfaces that need to be tested. +type testBlock struct{} + +func (*testBlock) BlockSize() int { return 0 } +func (*testBlock) Encrypt(a, b []byte) {} +func (*testBlock) Decrypt(a, b []byte) {} +func (*testBlock) NewGCM(int) (cipher.AEAD, error) { + return &testAEAD{}, nil +} +func (*testBlock) NewCBCEncrypter([]byte) cipher.BlockMode { + return &testBlockMode{} +} +func (*testBlock) NewCBCDecrypter([]byte) cipher.BlockMode { + return &testBlockMode{} +} +func (*testBlock) NewCTR([]byte) cipher.Stream { + return &testStream{} +} + +// testAEAD implements the cipher.AEAD interface. +type testAEAD struct{} + +func (*testAEAD) NonceSize() int { return 0 } +func (*testAEAD) Overhead() int { return 0 } +func (*testAEAD) Seal(a, b, c, d []byte) []byte { return []byte{} } +func (*testAEAD) Open(a, b, c, d []byte) ([]byte, error) { return []byte{}, nil } +func (*testAEAD) InAESPackage() bool { return true } + +// Test the gcmAble interface is detected correctly by the cipher package. +func TestGCMAble(t *testing.T) { + b := cipher.Block(&testBlock{}) + if _, ok := b.(gcmAble); !ok { + t.Fatalf("testBlock does not implement the gcmAble interface") + } + aead, err := cipher.NewGCM(b) + if err != nil { + t.Fatalf("%v", err) + } + if _, ok := aead.(testInterface); !ok { + t.Fatalf("cipher.NewGCM did not use gcmAble interface") + } +} + +// testBlockMode implements the cipher.BlockMode interface. +type testBlockMode struct{} + +func (*testBlockMode) BlockSize() int { return 0 } +func (*testBlockMode) CryptBlocks(a, b []byte) {} +func (*testBlockMode) InAESPackage() bool { return true } + +// Test the cbcEncAble interface is detected correctly by the cipher package. +func TestCBCEncAble(t *testing.T) { + b := cipher.Block(&testBlock{}) + if _, ok := b.(cbcEncAble); !ok { + t.Fatalf("testBlock does not implement the cbcEncAble interface") + } + bm := cipher.NewCBCEncrypter(b, []byte{}) + if _, ok := bm.(testInterface); !ok { + t.Fatalf("cipher.NewCBCEncrypter did not use cbcEncAble interface") + } +} + +// Test the cbcDecAble interface is detected correctly by the cipher package. +func TestCBCDecAble(t *testing.T) { + b := cipher.Block(&testBlock{}) + if _, ok := b.(cbcDecAble); !ok { + t.Fatalf("testBlock does not implement the cbcDecAble interface") + } + bm := cipher.NewCBCDecrypter(b, []byte{}) + if _, ok := bm.(testInterface); !ok { + t.Fatalf("cipher.NewCBCDecrypter did not use cbcDecAble interface") + } +} + +// testStream implements the cipher.Stream interface. +type testStream struct{} + +func (*testStream) XORKeyStream(a, b []byte) {} +func (*testStream) InAESPackage() bool { return true } + +// Test the ctrAble interface is detected correctly by the cipher package. +func TestCTRAble(t *testing.T) { + b := cipher.Block(&testBlock{}) + if _, ok := b.(ctrAble); !ok { + t.Fatalf("testBlock does not implement the ctrAble interface") + } + s := cipher.NewCTR(b, []byte{}) + if _, ok := s.(testInterface); !ok { + t.Fatalf("cipher.NewCTR did not use ctrAble interface") + } +} diff --git a/libgo/go/crypto/cipher/cbc.go b/libgo/go/crypto/cipher/cbc.go index 241e122..0367d59 100644 --- a/libgo/go/crypto/cipher/cbc.go +++ b/libgo/go/crypto/cipher/cbc.go @@ -29,6 +29,14 @@ func newCBC(b Block, iv []byte) *cbc { type cbcEncrypter cbc +// cbcEncAble is an interface implemented by ciphers that have a specific +// optimized implementation of CBC encryption, like crypto/aes. +// NewCBCEncrypter will check for this interface and return the specific +// BlockMode if found. +type cbcEncAble interface { + NewCBCEncrypter(iv []byte) BlockMode +} + // NewCBCEncrypter returns a BlockMode which encrypts in cipher block chaining // mode, using the given Block. The length of iv must be the same as the // Block's block size. @@ -36,6 +44,9 @@ func NewCBCEncrypter(b Block, iv []byte) BlockMode { if len(iv) != b.BlockSize() { panic("cipher.NewCBCEncrypter: IV length must equal block size") } + if cbc, ok := b.(cbcEncAble); ok { + return cbc.NewCBCEncrypter(iv) + } return (*cbcEncrypter)(newCBC(b, iv)) } @@ -75,6 +86,14 @@ func (x *cbcEncrypter) SetIV(iv []byte) { type cbcDecrypter cbc +// cbcDecAble is an interface implemented by ciphers that have a specific +// optimized implementation of CBC decryption, like crypto/aes. +// NewCBCDecrypter will check for this interface and return the specific +// BlockMode if found. +type cbcDecAble interface { + NewCBCDecrypter(iv []byte) BlockMode +} + // NewCBCDecrypter returns a BlockMode which decrypts in cipher block chaining // mode, using the given Block. The length of iv must be the same as the // Block's block size and must match the iv used to encrypt the data. @@ -82,6 +101,9 @@ func NewCBCDecrypter(b Block, iv []byte) BlockMode { if len(iv) != b.BlockSize() { panic("cipher.NewCBCDecrypter: IV length must equal block size") } + if cbc, ok := b.(cbcDecAble); ok { + return cbc.NewCBCDecrypter(iv) + } return (*cbcDecrypter)(newCBC(b, iv)) } diff --git a/libgo/go/crypto/cipher/cipher.go b/libgo/go/crypto/cipher/cipher.go index 7d27fde..531ecad 100644 --- a/libgo/go/crypto/cipher/cipher.go +++ b/libgo/go/crypto/cipher/cipher.go @@ -9,8 +9,8 @@ package cipher // A Block represents an implementation of block cipher -// using a given key. It provides the capability to encrypt -// or decrypt individual blocks. The mode implementations +// using a given key. It provides the capability to encrypt +// or decrypt individual blocks. The mode implementations // extend that capability to streams of blocks. type Block interface { // BlockSize returns the cipher's block size. diff --git a/libgo/go/crypto/cipher/cipher_test.go b/libgo/go/crypto/cipher/cipher_test.go index 8da5bce..1faa7b8 100644 --- a/libgo/go/crypto/cipher/cipher_test.go +++ b/libgo/go/crypto/cipher/cipher_test.go @@ -1,4 +1,4 @@ -// Copyright 2013 The Go Authors. All rights reserved. +// Copyright 2013 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. diff --git a/libgo/go/crypto/cipher/ctr.go b/libgo/go/crypto/cipher/ctr.go index 16baa6d..75f46cf 100644 --- a/libgo/go/crypto/cipher/ctr.go +++ b/libgo/go/crypto/cipher/ctr.go @@ -21,9 +21,19 @@ type ctr struct { const streamBufferSize = 512 +// ctrAble is an interface implemented by ciphers that have a specific optimized +// implementation of CTR, like crypto/aes. NewCTR will check for this interface +// and return the specific Stream if found. +type ctrAble interface { + NewCTR(iv []byte) Stream +} + // NewCTR returns a Stream which encrypts/decrypts using the given Block in // counter mode. The length of iv must be the same as the Block's block size. func NewCTR(block Block, iv []byte) Stream { + if ctr, ok := block.(ctrAble); ok { + return ctr.NewCTR(iv) + } if len(iv) != block.BlockSize() { panic("cipher.NewCTR: IV length must equal block size") } diff --git a/libgo/go/crypto/cipher/example_test.go b/libgo/go/crypto/cipher/example_test.go index f6cc386..9abe782 100644 --- a/libgo/go/crypto/cipher/example_test.go +++ b/libgo/go/crypto/cipher/example_test.go @@ -44,9 +44,9 @@ func ExampleNewGCMDecrypter() { // The key argument should be the AES key, either 16 or 32 bytes // to select AES-128 or AES-256. key := []byte("AES256Key-32Characters1234567890") - ciphertext, _ := hex.DecodeString("f90fbef747e7212ad7410d0eee2d965de7e890471695cddd2a5bc0ef5da1d04ad8147b62141ad6e4914aee8c512f64fba9037603d41de0d50b718bd665f019cdcd") + ciphertext, _ := hex.DecodeString("1019aa66cd7c024f9efd0038899dae1973ee69427f5a6579eba292ffe1b5a260") - nonce, _ := hex.DecodeString("bb8ef84243d2ee95a41c6c57") + nonce, _ := hex.DecodeString("37b8e8a308c354048d245f6d") block, err := aes.NewCipher(key) if err != nil { @@ -63,7 +63,8 @@ func ExampleNewGCMDecrypter() { panic(err.Error()) } - fmt.Printf("%s\n", string(plaintext)) + fmt.Printf("%s\n", plaintext) + // Output: exampleplaintext } func ExampleNewCBCDecrypter() { diff --git a/libgo/go/crypto/cipher/xor.go b/libgo/go/crypto/cipher/xor.go index f88dc89..01ca0a9 100644 --- a/libgo/go/crypto/cipher/xor.go +++ b/libgo/go/crypto/cipher/xor.go @@ -10,7 +10,7 @@ import ( ) const wordSize = int(unsafe.Sizeof(uintptr(0))) -const supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "amd64" +const supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "amd64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x" // fastXORBytes xors in bulk. It only works on architectures that // support unaligned read/writes. diff --git a/libgo/go/crypto/cipher/xor_test.go b/libgo/go/crypto/cipher/xor_test.go index cc1c9d7..d9187eb 100644 --- a/libgo/go/crypto/cipher/xor_test.go +++ b/libgo/go/crypto/cipher/xor_test.go @@ -19,7 +19,7 @@ func TestXOR(t *testing.T) { d2 := make([]byte, 1024+alignD)[alignD:] xorBytes(d1, p, q) safeXORBytes(d2, p, q) - if bytes.Compare(d1, d2) != 0 { + if !bytes.Equal(d1, d2) { t.Error("not equal") } } diff --git a/libgo/go/crypto/des/block.go b/libgo/go/crypto/des/block.go index 26355a2..99338d6 100644 --- a/libgo/go/crypto/des/block.go +++ b/libgo/go/crypto/des/block.go @@ -72,7 +72,7 @@ func init() { for i := 0; i < 4; i++ { for j := 0; j < 16; j++ { f := uint64(sBoxes[s][i][j]) << (4 * (7 - uint(s))) - f = permuteBlock(uint64(f), permutationFunction[:]) + f = permuteBlock(f, permutationFunction[:]) feistelBox[s][16*i+j] = uint32(f) } } diff --git a/libgo/go/crypto/dsa/dsa.go b/libgo/go/crypto/dsa/dsa.go index 9f414a4..e9b6a0c 100644 --- a/libgo/go/crypto/dsa/dsa.go +++ b/libgo/go/crypto/dsa/dsa.go @@ -52,7 +52,7 @@ const numMRTests = 64 // GenerateParameters puts a random, valid set of DSA parameters into params. // This function can take many seconds, even on fast machines. -func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes) (err error) { +func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes) error { // This function doesn't follow FIPS 186-3 exactly in that it doesn't // use a verification seed to generate the primes. The verification // seed doesn't appear to be exported or used by other code and @@ -87,9 +87,8 @@ func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes GeneratePrimes: for { - _, err = io.ReadFull(rand, qBytes) - if err != nil { - return + if _, err := io.ReadFull(rand, qBytes); err != nil { + return err } qBytes[len(qBytes)-1] |= 1 @@ -101,9 +100,8 @@ GeneratePrimes: } for i := 0; i < 4*L; i++ { - _, err = io.ReadFull(rand, pBytes) - if err != nil { - return + if _, err := io.ReadFull(rand, pBytes); err != nil { + return err } pBytes[len(pBytes)-1] |= 1 @@ -142,7 +140,7 @@ GeneratePrimes: } params.G = g - return + return nil } } diff --git a/libgo/go/crypto/ecdsa/ecdsa.go b/libgo/go/crypto/ecdsa/ecdsa.go index e54488c..72fb499 100644 --- a/libgo/go/crypto/ecdsa/ecdsa.go +++ b/libgo/go/crypto/ecdsa/ecdsa.go @@ -97,17 +97,17 @@ func randFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error) } // GenerateKey generates a public and private key pair. -func GenerateKey(c elliptic.Curve, rand io.Reader) (priv *PrivateKey, err error) { +func GenerateKey(c elliptic.Curve, rand io.Reader) (*PrivateKey, error) { k, err := randFieldElement(c, rand) if err != nil { - return + return nil, err } - priv = new(PrivateKey) + priv := new(PrivateKey) priv.PublicKey.Curve = c priv.D = k priv.PublicKey.X, priv.PublicKey.Y = c.ScalarBaseMult(k.Bytes()) - return + return priv, nil } // hashToInt converts a hash value to an integer. There is some disagreement @@ -143,10 +143,11 @@ func fermatInverse(k, N *big.Int) *big.Int { var errZeroParam = errors.New("zero parameter") -// Sign signs an arbitrary length hash (which should be the result of hashing a -// larger message) using the private key, priv. It returns the signature as a -// pair of integers. The security of the private key depends on the entropy of -// rand. +// Sign signs a hash (which should be the result of hashing a larger message) +// using the private key, priv. If the hash is longer than the bit-length of the +// private key's curve order, the hash will be truncated to that length. It +// returns the signature as a pair of integers. The security of the private key +// depends on the entropy of rand. func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) { // Get max(log2(q) / 2, 256) bits of entropy from rand. entropylen := (priv.Curve.Params().BitSize + 7) / 16 @@ -228,7 +229,7 @@ func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool { c := pub.Curve N := c.Params().N - if r.Sign() == 0 || s.Sign() == 0 { + if r.Sign() <= 0 || s.Sign() <= 0 { return false } if r.Cmp(N) >= 0 || s.Cmp(N) >= 0 { diff --git a/libgo/go/crypto/ecdsa/ecdsa_test.go b/libgo/go/crypto/ecdsa/ecdsa_test.go index 62a3fcc..fc25fd7 100644 --- a/libgo/go/crypto/ecdsa/ecdsa_test.go +++ b/libgo/go/crypto/ecdsa/ecdsa_test.go @@ -130,7 +130,7 @@ func testNonceSafety(t *testing.T, c elliptic.Curve, tag string) { } if r0.Cmp(r1) == 0 { - t.Errorf("%s: the nonce used for two diferent messages was the same", tag) + t.Errorf("%s: the nonce used for two different messages was the same", tag) } } @@ -296,3 +296,26 @@ func TestVectors(t *testing.T) { } } } + +func testNegativeInputs(t *testing.T, curve elliptic.Curve, tag string) { + key, err := GenerateKey(curve, rand.Reader) + if err != nil { + t.Errorf("failed to generate key for %q", tag) + } + + var hash [32]byte + r := new(big.Int).SetInt64(1) + r.Lsh(r, 550 /* larger than any supported curve */) + r.Neg(r) + + if Verify(&key.PublicKey, hash[:], r, r) { + t.Errorf("bogus signature accepted for %q", tag) + } +} + +func TestNegativeInputs(t *testing.T) { + testNegativeInputs(t, elliptic.P224(), "p224") + testNegativeInputs(t, elliptic.P256(), "p256") + testNegativeInputs(t, elliptic.P384(), "p384") + testNegativeInputs(t, elliptic.P521(), "p521") +} diff --git a/libgo/go/crypto/elliptic/p224.go b/libgo/go/crypto/elliptic/p224.go index 2d3fac7..de266ca 100644 --- a/libgo/go/crypto/elliptic/p224.go +++ b/libgo/go/crypto/elliptic/p224.go @@ -1,4 +1,4 @@ -// Copyright 2012 The Go Authors. All rights reserved. +// 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. diff --git a/libgo/go/crypto/elliptic/p224_test.go b/libgo/go/crypto/elliptic/p224_test.go index 4b26d16..8b4fa04 100644 --- a/libgo/go/crypto/elliptic/p224_test.go +++ b/libgo/go/crypto/elliptic/p224_test.go @@ -1,4 +1,4 @@ -// Copyright 2012 The Go Authors. All rights reserved. +// 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. diff --git a/libgo/go/crypto/elliptic/p256.go b/libgo/go/crypto/elliptic/p256.go index 5103e86..05a3311 100644 --- a/libgo/go/crypto/elliptic/p256.go +++ b/libgo/go/crypto/elliptic/p256.go @@ -1,4 +1,4 @@ -// Copyright 2013 The Go Authors. All rights reserved. +// Copyright 2013 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. @@ -1056,7 +1056,7 @@ func p256ScalarBaseMult(xOut, yOut, zOut *[p256Limbs]uint32, scalar *[32]uint8) p256CopyConditional(yOut, &ty, mask) p256CopyConditional(zOut, &tz, mask) // If p was not zero, then n is now non-zero. - nIsInfinityMask &= ^pIsNoninfiniteMask + nIsInfinityMask &^= pIsNoninfiniteMask } } } @@ -1136,7 +1136,7 @@ func p256ScalarMult(xOut, yOut, zOut, x, y *[p256Limbs]uint32, scalar *[32]uint8 p256CopyConditional(xOut, &tx, mask) p256CopyConditional(yOut, &ty, mask) p256CopyConditional(zOut, &tz, mask) - nIsInfinityMask &= ^pIsNoninfiniteMask + nIsInfinityMask &^= pIsNoninfiniteMask } } diff --git a/libgo/go/crypto/elliptic/p256_amd64.go b/libgo/go/crypto/elliptic/p256_amd64.go index 586cd10..66b7cf8 100644 --- a/libgo/go/crypto/elliptic/p256_amd64.go +++ b/libgo/go/crypto/elliptic/p256_amd64.go @@ -66,7 +66,7 @@ func p256NegCond(val []uint64, cond int) // if cond == 0 res <- b; else res <- a func p256MovCond(res, a, b []uint64, cond int) -// Endianess swap +// Endianness swap func p256BigToLittle(res []uint64, in []byte) func p256LittleToBig(res []byte, in []uint64) @@ -93,10 +93,14 @@ func p256PointAddAsm(res, in1, in2 []uint64) func p256PointDoubleAsm(res, in []uint64) func (curve p256Curve) Inverse(k *big.Int) *big.Int { + if k.Sign() < 0 { + // This should never happen. + k = new(big.Int).Neg(k) + } + if k.Cmp(p256.N) >= 0 { // This should never happen. - reducedK := new(big.Int).Mod(k, p256.N) - k = reducedK + k = new(big.Int).Mod(k, p256.N) } // table will store precomputed powers of x. The four words at index diff --git a/libgo/go/crypto/hmac/hmac.go b/libgo/go/crypto/hmac/hmac.go index 3b41cde..a748107 100644 --- a/libgo/go/crypto/hmac/hmac.go +++ b/libgo/go/crypto/hmac/hmac.go @@ -37,26 +37,16 @@ import ( type hmac struct { size int blocksize int - key, tmp []byte + opad, ipad []byte outer, inner hash.Hash } -func (h *hmac) tmpPad(xor byte) { - for i, k := range h.key { - h.tmp[i] = xor ^ k - } - for i := len(h.key); i < h.blocksize; i++ { - h.tmp[i] = xor - } -} - func (h *hmac) Sum(in []byte) []byte { origLen := len(in) in = h.inner.Sum(in) - h.tmpPad(0x5c) - copy(h.tmp[h.blocksize:], in[origLen:]) h.outer.Reset() - h.outer.Write(h.tmp) + h.outer.Write(h.opad) + h.outer.Write(in[origLen:]) return h.outer.Sum(in[:origLen]) } @@ -70,8 +60,7 @@ func (h *hmac) BlockSize() int { return h.blocksize } func (h *hmac) Reset() { h.inner.Reset() - h.tmpPad(0x36) - h.inner.Write(h.tmp[:h.blocksize]) + h.inner.Write(h.ipad) } // New returns a new HMAC hash using the given hash.Hash type and key. @@ -81,15 +70,22 @@ func New(h func() hash.Hash, key []byte) hash.Hash { hm.inner = h() hm.size = hm.inner.Size() hm.blocksize = hm.inner.BlockSize() - hm.tmp = make([]byte, hm.blocksize+hm.size) + hm.ipad = make([]byte, hm.blocksize) + hm.opad = make([]byte, hm.blocksize) if len(key) > hm.blocksize { // If key is too big, hash it. hm.outer.Write(key) key = hm.outer.Sum(nil) } - hm.key = make([]byte, len(key)) - copy(hm.key, key) - hm.Reset() + copy(hm.ipad, key) + copy(hm.opad, key) + for i := range hm.ipad { + hm.ipad[i] ^= 0x36 + } + for i := range hm.opad { + hm.opad[i] ^= 0x5c + } + hm.inner.Write(hm.ipad) return hm } diff --git a/libgo/go/crypto/hmac/hmac_test.go b/libgo/go/crypto/hmac/hmac_test.go index e80b7e0..aac9aa9 100644 --- a/libgo/go/crypto/hmac/hmac_test.go +++ b/libgo/go/crypto/hmac/hmac_test.go @@ -568,3 +568,29 @@ func TestEqual(t *testing.T) { t.Error("Equal accepted unequal slices") } } + +func BenchmarkHMACSHA256_1K(b *testing.B) { + key := make([]byte, 32) + buf := make([]byte, 1024) + h := New(sha256.New, key) + b.SetBytes(int64(len(buf))) + for i := 0; i < b.N; i++ { + h.Write(buf) + h.Reset() + mac := h.Sum(nil) + buf[0] = mac[0] + } +} + +func BenchmarkHMACSHA256_32(b *testing.B) { + key := make([]byte, 32) + buf := make([]byte, 32) + h := New(sha256.New, key) + b.SetBytes(int64(len(buf))) + for i := 0; i < b.N; i++ { + h.Write(buf) + h.Reset() + mac := h.Sum(nil) + buf[0] = mac[0] + } +} diff --git a/libgo/go/crypto/md5/gen.go b/libgo/go/crypto/md5/gen.go index 8cd0a63..178fad1 100644 --- a/libgo/go/crypto/md5/gen.go +++ b/libgo/go/crypto/md5/gen.go @@ -1,4 +1,4 @@ -// Copyright 2012 The Go Authors. All rights reserved. +// 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. diff --git a/libgo/go/crypto/md5/md5.go b/libgo/go/crypto/md5/md5.go index a3550cb..ce58d5e 100644 --- a/libgo/go/crypto/md5/md5.go +++ b/libgo/go/crypto/md5/md5.go @@ -89,7 +89,7 @@ func (d0 *digest) Sum(in []byte) []byte { } func (d *digest) checkSum() [Size]byte { - // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. + // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. len := d.len var tmp [64]byte tmp[0] = 0x80 diff --git a/libgo/go/crypto/md5/md5block_decl.go b/libgo/go/crypto/md5/md5block_decl.go index d7956a6..1e6f6e6 100644 --- a/libgo/go/crypto/md5/md5block_decl.go +++ b/libgo/go/crypto/md5/md5block_decl.go @@ -1,8 +1,8 @@ -// Copyright 2013 The Go Authors. All rights reserved. +// Copyright 2013 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 amd64 amd64p32 386 arm +// +build amd64 amd64p32 386 arm ppc64le s390x package md5 diff --git a/libgo/go/crypto/md5/md5block_generic.go b/libgo/go/crypto/md5/md5block_generic.go index 263463e..726e09b 100644 --- a/libgo/go/crypto/md5/md5block_generic.go +++ b/libgo/go/crypto/md5/md5block_generic.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !amd64,!amd64p32,!386,!arm +// +build !amd64,!amd64p32,!386,!arm,!ppc64le,!s390x package md5 diff --git a/libgo/go/crypto/rand/eagain.go b/libgo/go/crypto/rand/eagain.go index 2c853d0..7ed2f47 100644 --- a/libgo/go/crypto/rand/eagain.go +++ b/libgo/go/crypto/rand/eagain.go @@ -1,4 +1,4 @@ -// Copyright 2014 The Go Authors. All rights reserved. +// Copyright 2014 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. diff --git a/libgo/go/crypto/rand/rand.go b/libgo/go/crypto/rand/rand.go index ee32fa0..6f7523d 100644 --- a/libgo/go/crypto/rand/rand.go +++ b/libgo/go/crypto/rand/rand.go @@ -1,4 +1,4 @@ -// Copyright 2010 The Go Authors. All rights reserved. +// 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. @@ -11,8 +11,9 @@ import "io" // Reader is a global, shared instance of a cryptographically // strong pseudo-random generator. // -// On Unix-like systems, Reader reads from /dev/urandom. // On Linux, Reader uses getrandom(2) if available, /dev/urandom otherwise. +// On OpenBSD, Reader uses getentropy(2). +// On other Unix-like systems, Reader reads from /dev/urandom. // On Windows systems, Reader uses the CryptGenRandom API. var Reader io.Reader diff --git a/libgo/go/crypto/rand/rand_linux.go b/libgo/go/crypto/rand/rand_linux.go index 7d6d9e8..472daa7 100644 --- a/libgo/go/crypto/rand/rand_linux.go +++ b/libgo/go/crypto/rand/rand_linux.go @@ -1,4 +1,4 @@ -// Copyright 2014 The Go Authors. All rights reserved. +// Copyright 2014 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. diff --git a/libgo/go/crypto/rand/rand_openbsd.go b/libgo/go/crypto/rand/rand_openbsd.go new file mode 100644 index 0000000..9cc39f7 --- /dev/null +++ b/libgo/go/crypto/rand/rand_openbsd.go @@ -0,0 +1,28 @@ +// Copyright 2016 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 rand + +import ( + "internal/syscall/unix" +) + +func init() { + altGetRandom = getRandomOpenBSD +} + +func getRandomOpenBSD(p []byte) (ok bool) { + // getentropy(2) returns a maximum of 256 bytes per call + for i := 0; i < len(p); i += 256 { + end := i + 256 + if len(p) < end { + end = len(p) + } + err := unix.GetEntropy(p[i:end]) + if err != nil { + return false + } + } + return true +} diff --git a/libgo/go/crypto/rand/rand_test.go b/libgo/go/crypto/rand/rand_test.go index e46e61d..e45f58e 100644 --- a/libgo/go/crypto/rand/rand_test.go +++ b/libgo/go/crypto/rand/rand_test.go @@ -1,4 +1,4 @@ -// Copyright 2010 The Go Authors. All rights reserved. +// 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. diff --git a/libgo/go/crypto/rand/rand_unix.go b/libgo/go/crypto/rand/rand_unix.go index 75c36e0..631972b 100644 --- a/libgo/go/crypto/rand/rand_unix.go +++ b/libgo/go/crypto/rand/rand_unix.go @@ -1,4 +1,4 @@ -// Copyright 2010 The Go Authors. All rights reserved. +// 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. @@ -84,7 +84,7 @@ func (hr hideAgainReader) Read(p []byte) (n int, err error) { // systems without a reliable /dev/urandom. // newReader returns a new pseudorandom generator that -// seeds itself by reading from entropy. If entropy == nil, +// seeds itself by reading from entropy. If entropy == nil, // the generator seeds itself by reading from the system's // random number generator, typically /dev/random. // The Read method on the returned reader always returns diff --git a/libgo/go/crypto/rand/rand_windows.go b/libgo/go/crypto/rand/rand_windows.go index 82b39b6..4d7511a 100644 --- a/libgo/go/crypto/rand/rand_windows.go +++ b/libgo/go/crypto/rand/rand_windows.go @@ -1,4 +1,4 @@ -// Copyright 2010 The Go Authors. All rights reserved. +// 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. diff --git a/libgo/go/crypto/rand/util.go b/libgo/go/crypto/rand/util.go index 5f74407..592c57e 100644 --- a/libgo/go/crypto/rand/util.go +++ b/libgo/go/crypto/rand/util.go @@ -1,4 +1,4 @@ -// Copyright 2011 The Go Authors. All rights reserved. +// Copyright 2011 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. @@ -70,7 +70,7 @@ func Prime(rand io.Reader, bits int) (p *big.Int, err error) { p.SetBytes(bytes) - // Calculate the value mod the product of smallPrimes. If it's + // Calculate the value mod the product of smallPrimes. If it's // a multiple of any of these primes we add two until it isn't. // The probability of overflowing is minimal and can be ignored // because we still perform Miller-Rabin tests on the result. diff --git a/libgo/go/crypto/rand/util_test.go b/libgo/go/crypto/rand/util_test.go index 2f7cba8..7b07689 100644 --- a/libgo/go/crypto/rand/util_test.go +++ b/libgo/go/crypto/rand/util_test.go @@ -1,4 +1,4 @@ -// Copyright 2013 The Go Authors. All rights reserved. +// Copyright 2013 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. diff --git a/libgo/go/crypto/rc4/rc4.go b/libgo/go/crypto/rc4/rc4.go index 9acb681..bd04aee 100644 --- a/libgo/go/crypto/rc4/rc4.go +++ b/libgo/go/crypto/rc4/rc4.go @@ -23,7 +23,7 @@ func (k KeySizeError) Error() string { return "crypto/rc4: invalid key size " + strconv.Itoa(int(k)) } -// NewCipher creates and returns a new Cipher. The key argument should be the +// NewCipher creates and returns a new Cipher. The key argument should be the // RC4 key, at least 1 byte and at most 256 bytes. func NewCipher(key []byte) (*Cipher, error) { k := len(key) @@ -52,7 +52,7 @@ func (c *Cipher) Reset() { } // xorKeyStreamGeneric sets dst to the result of XORing src with the -// key stream. Dst and src may be the same slice but otherwise should +// key stream. Dst and src may be the same slice but otherwise should // not overlap. // // This is the pure Go version. rc4_{amd64,386,arm}* contain assembly diff --git a/libgo/go/crypto/rsa/pkcs1v15.go b/libgo/go/crypto/rsa/pkcs1v15.go index 5c5f415..3517a8c 100644 --- a/libgo/go/crypto/rsa/pkcs1v15.go +++ b/libgo/go/crypto/rsa/pkcs1v15.go @@ -24,31 +24,32 @@ type PKCS1v15DecryptOptions struct { SessionKeyLen int } -// EncryptPKCS1v15 encrypts the given message with RSA and the padding scheme from PKCS#1 v1.5. -// The message must be no longer than the length of the public modulus minus 11 bytes. +// EncryptPKCS1v15 encrypts the given message with RSA and the padding +// scheme from PKCS#1 v1.5. The message must be no longer than the +// length of the public modulus minus 11 bytes. // -// The rand parameter is used as a source of entropy to ensure that encrypting -// the same message twice doesn't result in the same ciphertext. +// The rand parameter is used as a source of entropy to ensure that +// encrypting the same message twice doesn't result in the same +// ciphertext. // -// WARNING: use of this function to encrypt plaintexts other than session keys -// is dangerous. Use RSA OAEP in new protocols. -func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, err error) { +// WARNING: use of this function to encrypt plaintexts other than +// session keys is dangerous. Use RSA OAEP in new protocols. +func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) ([]byte, error) { if err := checkPub(pub); err != nil { return nil, err } k := (pub.N.BitLen() + 7) / 8 if len(msg) > k-11 { - err = ErrMessageTooLong - return + return nil, ErrMessageTooLong } // EM = 0x00 || 0x02 || PS || 0x00 || M em := make([]byte, k) em[1] = 2 ps, mm := em[2:len(em)-len(msg)-1], em[len(em)-len(msg):] - err = nonZeroRandomBytes(ps, rand) + err := nonZeroRandomBytes(ps, rand) if err != nil { - return + return nil, err } em[len(em)-len(msg)-1] = 0 copy(mm, msg) @@ -57,8 +58,7 @@ func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, er c := encrypt(new(big.Int), pub, m) copyWithLeftPad(em, c.Bytes()) - out = em - return + return em, nil } // DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5. @@ -69,19 +69,18 @@ func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, er // learn whether each instance returned an error then they can decrypt and // forge signatures as if they had the private key. See // DecryptPKCS1v15SessionKey for a way of solving this problem. -func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out []byte, err error) { +func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) ([]byte, error) { if err := checkPub(&priv.PublicKey); err != nil { return nil, err } valid, out, index, err := decryptPKCS1v15(rand, priv, ciphertext) if err != nil { - return + return nil, err } if valid == 0 { return nil, ErrDecryption } - out = out[index:] - return + return out[index:], nil } // DecryptPKCS1v15SessionKey decrypts a session key using RSA and the padding scheme from PKCS#1 v1.5. @@ -103,7 +102,7 @@ func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out [ // a random value was used (because it'll be different for the same ciphertext) // and thus whether the padding was correct. This defeats the point of this // function. Using at least a 16-byte key will protect against this attack. -func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) (err error) { +func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) error { if err := checkPub(&priv.PublicKey); err != nil { return err } @@ -114,7 +113,7 @@ func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []by valid, em, index, err := decryptPKCS1v15(rand, priv, ciphertext) if err != nil { - return + return err } if len(em) != k { @@ -125,7 +124,7 @@ func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []by valid &= subtle.ConstantTimeEq(int32(len(em)-index), int32(len(key))) subtle.ConstantTimeCopy(valid, key, em[len(em)-len(key):]) - return + return nil } // decryptPKCS1v15 decrypts ciphertext using priv and blinds the operation if @@ -213,21 +212,23 @@ var hashPrefixes = map[crypto.Hash][]byte{ crypto.RIPEMD160: {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31, 0x04, 0x14}, } -// SignPKCS1v15 calculates the signature of hashed using RSASSA-PKCS1-V1_5-SIGN from RSA PKCS#1 v1.5. -// Note that hashed must be the result of hashing the input message using the -// given hash function. If hash is zero, hashed is signed directly. This isn't +// SignPKCS1v15 calculates the signature of hashed using +// RSASSA-PKCS1-V1_5-SIGN from RSA PKCS#1 v1.5. Note that hashed must +// be the result of hashing the input message using the given hash +// function. If hash is zero, hashed is signed directly. This isn't // advisable except for interoperability. // -// If rand is not nil then RSA blinding will be used to avoid timing side-channel attacks. +// If rand is not nil then RSA blinding will be used to avoid timing +// side-channel attacks. // -// This function is deterministic. Thus, if the set of possible messages is -// small, an attacker may be able to build a map from messages to signatures -// and identify the signed messages. As ever, signatures provide authenticity, -// not confidentiality. -func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) (s []byte, err error) { +// This function is deterministic. Thus, if the set of possible +// messages is small, an attacker may be able to build a map from +// messages to signatures and identify the signed messages. As ever, +// signatures provide authenticity, not confidentiality. +func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) { hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed)) if err != nil { - return + return nil, err } tLen := len(prefix) + hashLen @@ -248,12 +249,11 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []b m := new(big.Int).SetBytes(em) c, err := decryptAndCheck(rand, priv, m) if err != nil { - return + return nil, err } copyWithLeftPad(em, c.Bytes()) - s = em - return + return em, nil } // VerifyPKCS1v15 verifies an RSA PKCS#1 v1.5 signature. @@ -261,17 +261,16 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []b // function and sig is the signature. A valid signature is indicated by // returning a nil error. If hash is zero then hashed is used directly. This // isn't advisable except for interoperability. -func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) (err error) { +func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) error { hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed)) if err != nil { - return + return err } tLen := len(prefix) + hashLen k := (pub.N.BitLen() + 7) / 8 if k < tLen+11 { - err = ErrVerification - return + return ErrVerification } c := new(big.Int).SetBytes(sig) diff --git a/libgo/go/crypto/rsa/pss.go b/libgo/go/crypto/rsa/pss.go index 8a94589..1ba194a 100644 --- a/libgo/go/crypto/rsa/pss.go +++ b/libgo/go/crypto/rsa/pss.go @@ -64,7 +64,7 @@ func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byt hash.Reset() // 7. Generate an octet string PS consisting of emLen - sLen - hLen - 2 - // zero octets. The length of PS may be 0. + // zero octets. The length of PS may be 0. // // 8. Let DB = PS || 0x01 || salt; DB is an octet string of length // emLen - hLen - 1. @@ -246,7 +246,7 @@ func (opts *PSSOptions) saltLength() int { // Note that hashed must be the result of hashing the input message using the // given hash function. The opts argument may be nil, in which case sensible // defaults are used. -func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte, opts *PSSOptions) (s []byte, err error) { +func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte, opts *PSSOptions) ([]byte, error) { saltLength := opts.saltLength() switch saltLength { case PSSSaltLengthAuto: @@ -260,8 +260,8 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte, } salt := make([]byte, saltLength) - if _, err = io.ReadFull(rand, salt); err != nil { - return + if _, err := io.ReadFull(rand, salt); err != nil { + return nil, err } return signPSSWithSalt(rand, priv, hash, hashed, salt) } diff --git a/libgo/go/crypto/rsa/rsa.go b/libgo/go/crypto/rsa/rsa.go index 0f487fe..5943056 100644 --- a/libgo/go/crypto/rsa/rsa.go +++ b/libgo/go/crypto/rsa/rsa.go @@ -14,7 +14,7 @@ // possible. // // Two sets of interfaces are included in this package. When a more abstract -// interface isn't neccessary, there are functions for encrypting/decrypting +// interface isn't necessary, there are functions for encrypting/decrypting // with v1.5/OAEP and signing/verifying with v1.5/PSS. If one needs to abstract // over the public-key primitive, the PrivateKey struct implements the // Decrypter and Signer interfaces from the crypto package. @@ -191,7 +191,7 @@ func (priv *PrivateKey) Validate() error { // GenerateKey generates an RSA keypair of the given bit size using the // random source random (for example, crypto/rand.Reader). -func GenerateKey(random io.Reader, bits int) (priv *PrivateKey, err error) { +func GenerateKey(random io.Reader, bits int) (*PrivateKey, error) { return GenerateMultiPrimeKey(random, 2, bits) } @@ -206,8 +206,8 @@ func GenerateKey(random io.Reader, bits int) (priv *PrivateKey, err error) { // // [1] US patent 4405829 (1972, expired) // [2] http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf -func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (priv *PrivateKey, err error) { - priv = new(PrivateKey) +func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (*PrivateKey, error) { + priv := new(PrivateKey) priv.E = 65537 if nprimes < 2 { @@ -234,6 +234,7 @@ NextSetOfPrimes: todo += (nprimes - 2) / 5 } for i := 0; i < nprimes; i++ { + var err error primes[i], err = rand.Prime(random, todo/(nprimes-i)) if err != nil { return nil, err @@ -283,7 +284,7 @@ NextSetOfPrimes: } priv.Precompute() - return + return priv, nil } // incCounter increments a four byte, big-endian counter. @@ -348,15 +349,14 @@ func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int { // // The message must be no longer than the length of the public modulus less // twice the hash length plus 2. -func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) (out []byte, err error) { +func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) ([]byte, error) { if err := checkPub(pub); err != nil { return nil, err } hash.Reset() k := (pub.N.BitLen() + 7) / 8 if len(msg) > k-2*hash.Size()-2 { - err = ErrMessageTooLong - return + return nil, ErrMessageTooLong } hash.Write(label) @@ -371,9 +371,9 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l db[len(db)-len(msg)-1] = 1 copy(db[len(db)-len(msg):], msg) - _, err = io.ReadFull(random, seed) + _, err := io.ReadFull(random, seed) if err != nil { - return + return nil, err } mgf1XOR(db, hash, seed) @@ -382,7 +382,7 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l m := new(big.Int) m.SetBytes(em) c := encrypt(new(big.Int), pub, m) - out = c.Bytes() + out := c.Bytes() if len(out) < k { // If the output is too small, we need to left-pad with zeros. @@ -391,7 +391,7 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l out = t } - return + return out, nil } // ErrDecryption represents a failure to decrypt a message. @@ -565,22 +565,21 @@ func decryptAndCheck(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int // // The label parameter must match the value given when encrypting. See // EncryptOAEP for details. -func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) (msg []byte, err error) { +func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) ([]byte, error) { if err := checkPub(&priv.PublicKey); err != nil { return nil, err } k := (priv.N.BitLen() + 7) / 8 if len(ciphertext) > k || k < hash.Size()*2+2 { - err = ErrDecryption - return + return nil, ErrDecryption } c := new(big.Int).SetBytes(ciphertext) m, err := decrypt(random, priv, c) if err != nil { - return + return nil, err } hash.Write(label) @@ -628,12 +627,10 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext } if firstByteIsZero&lHash2Good&^invalid&^lookingForIndex != 1 { - err = ErrDecryption - return + return nil, ErrDecryption } - msg = rest[index+1:] - return + return rest[index+1:], nil } // leftPad returns a new slice of length size. The contents of input are right diff --git a/libgo/go/crypto/sha1/fallback_test.go b/libgo/go/crypto/sha1/fallback_test.go new file mode 100644 index 0000000..08acd04 --- /dev/null +++ b/libgo/go/crypto/sha1/fallback_test.go @@ -0,0 +1,34 @@ +// Copyright 2016 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 s390x + +package sha1 + +import ( + "fmt" + "io" + "testing" +) + +// Tests the fallback code path in case the optimized asm +// implementation cannot be used. +// See also TestBlockGeneric. +func TestGenericPath(t *testing.T) { + if useAsm == false { + t.Skipf("assembly implementation unavailable") + } + useAsm = false + defer func() { useAsm = true }() + c := New() + in := "ΑΒΓΔΕϜΖΗΘΙΚΛΜΝΞΟΠϺϘΡΣΤΥΦΧΨΩ" + gold := "0f58c2bb130f8182375f325c18342215255387e5" + if _, err := io.WriteString(c, in); err != nil { + t.Fatalf("could not write to c: %v", err) + } + out := fmt.Sprintf("%x", c.Sum(nil)) + if out != gold { + t.Fatalf("mismatch: got %s, wanted %s", out, gold) + } +} diff --git a/libgo/go/crypto/sha1/issue15617_test.go b/libgo/go/crypto/sha1/issue15617_test.go new file mode 100644 index 0000000..98038e5 --- /dev/null +++ b/libgo/go/crypto/sha1/issue15617_test.go @@ -0,0 +1,28 @@ +// +build amd64 +// +build linux darwin + +// Copyright 2016 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 sha1_test + +import ( + "crypto/sha1" + "syscall" + "testing" +) + +func TestOutOfBoundsRead(t *testing.T) { + const pageSize = 4 << 10 + data, err := syscall.Mmap(0, 0, 2*pageSize, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANON|syscall.MAP_PRIVATE) + if err != nil { + panic(err) + } + if err := syscall.Mprotect(data[pageSize:], syscall.PROT_NONE); err != nil { + panic(err) + } + for i := 0; i < pageSize; i++ { + sha1.Sum(data[pageSize-i : pageSize]) + } +} diff --git a/libgo/go/crypto/sha1/sha1.go b/libgo/go/crypto/sha1/sha1.go index 9f1a96e..ac593b1 100644 --- a/libgo/go/crypto/sha1/sha1.go +++ b/libgo/go/crypto/sha1/sha1.go @@ -90,7 +90,7 @@ func (d0 *digest) Sum(in []byte) []byte { func (d *digest) checkSum() [Size]byte { len := d.len - // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. + // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. var tmp [64]byte tmp[0] = 0x80 if len%64 < 56 { diff --git a/libgo/go/crypto/sha1/sha1_test.go b/libgo/go/crypto/sha1/sha1_test.go index 4a62951..214afc5 100644 --- a/libgo/go/crypto/sha1/sha1_test.go +++ b/libgo/go/crypto/sha1/sha1_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// SHA1 hash algorithm. See RFC 3174. +// SHA1 hash algorithm. See RFC 3174. package sha1 @@ -19,6 +19,7 @@ type sha1Test struct { } var golden = []sha1Test{ + {"76245dbf96f661bd221046197ab8b9f063f11bad", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"}, {"da39a3ee5e6b4b0d3255bfef95601890afd80709", ""}, {"86f7e437faa5a7fce15d1ddcb9eaeaea377667b8", "a"}, {"da23614e02469a0d7c7bd1bdab5c9c474b1904dc", "ab"}, @@ -91,15 +92,17 @@ func TestBlockSize(t *testing.T) { } } -// Tests that blockGeneric (pure Go) and block (in assembly for amd64, 386, arm) match. +// Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match. func TestBlockGeneric(t *testing.T) { - gen, asm := New().(*digest), New().(*digest) - buf := make([]byte, BlockSize*20) // arbitrary factor - rand.Read(buf) - blockGeneric(gen, buf) - block(asm, buf) - if *gen != *asm { - t.Error("block and blockGeneric resulted in different states") + for i := 1; i < 30; i++ { // arbitrary factor + gen, asm := New().(*digest), New().(*digest) + buf := make([]byte, BlockSize*i) + rand.Read(buf) + blockGeneric(gen, buf) + block(asm, buf) + if *gen != *asm { + t.Errorf("For %#v block and blockGeneric resulted in different states", buf) + } } } @@ -120,6 +123,10 @@ func BenchmarkHash8Bytes(b *testing.B) { benchmarkSize(b, 8) } +func BenchmarkHash320Bytes(b *testing.B) { + benchmarkSize(b, 320) +} + func BenchmarkHash1K(b *testing.B) { benchmarkSize(b, 1024) } diff --git a/libgo/go/crypto/sha1/sha1block_amd64.go b/libgo/go/crypto/sha1/sha1block_amd64.go new file mode 100644 index 0000000..fd85a42 --- /dev/null +++ b/libgo/go/crypto/sha1/sha1block_amd64.go @@ -0,0 +1,34 @@ +// Copyright 2016 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 sha1 + +//go:noescape + +func blockAVX2(dig *digest, p []byte) + +//go:noescape +func blockAMD64(dig *digest, p []byte) +func checkAVX2() bool + +var hasAVX2 = checkAVX2() + +func block(dig *digest, p []byte) { + if hasAVX2 && len(p) >= 256 { + // blockAVX2 calculates sha1 for 2 block per iteration + // it also interleaves precalculation for next block. + // So it may read up-to 192 bytes past end of p + // We may add checks inside blockAVX2, but this will + // just turn it into a copy of blockAMD64, + // so call it directly, instead. + safeLen := len(p) - 128 + if safeLen%128 != 0 { + safeLen -= 64 + } + blockAVX2(dig, p[:safeLen]) + blockAMD64(dig, p[safeLen:]) + } else { + blockAMD64(dig, p) + } +} diff --git a/libgo/go/crypto/sha1/sha1block_decl.go b/libgo/go/crypto/sha1/sha1block_decl.go index 24e521a..6d2d073 100644 --- a/libgo/go/crypto/sha1/sha1block_decl.go +++ b/libgo/go/crypto/sha1/sha1block_decl.go @@ -1,8 +1,8 @@ -// Copyright 2013 The Go Authors. All rights reserved. +// Copyright 2013 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 amd64 amd64p32 arm 386 +// +build amd64p32 arm 386 s390x package sha1 diff --git a/libgo/go/crypto/sha1/sha1block_generic.go b/libgo/go/crypto/sha1/sha1block_generic.go index 696e26b..f0194626 100644 --- a/libgo/go/crypto/sha1/sha1block_generic.go +++ b/libgo/go/crypto/sha1/sha1block_generic.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !amd64,!amd64p32,!386,!arm +// +build !amd64,!amd64p32,!386,!arm,!s390x package sha1 diff --git a/libgo/go/crypto/sha1/sha1block_s390x.go b/libgo/go/crypto/sha1/sha1block_s390x.go new file mode 100644 index 0000000..aac7c11 --- /dev/null +++ b/libgo/go/crypto/sha1/sha1block_s390x.go @@ -0,0 +1,12 @@ +// Copyright 2016 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 sha1 + +// featureCheck reports whether the CPU supports the +// SHA1 compute intermediate message digest (KIMD) +// function code. +func featureCheck() bool + +var useAsm = featureCheck() diff --git a/libgo/go/crypto/sha256/fallback_test.go b/libgo/go/crypto/sha256/fallback_test.go new file mode 100644 index 0000000..5917a48 --- /dev/null +++ b/libgo/go/crypto/sha256/fallback_test.go @@ -0,0 +1,35 @@ +// Copyright 2016 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 s390x + +package sha256 + +import ( + "fmt" + "io" + "testing" +) + +// Tests the fallback code path in case the optimized asm +// implementation cannot be used. +// See also TestBlockGeneric. +func TestGenericPath(t *testing.T) { + if useAsm == false { + t.Skipf("assembly implementation unavailable") + } + useAsm = false + defer func() { useAsm = true }() + c := New() + in := "ΑΒΓΔΕϜΖΗΘΙΚΛΜΝΞΟΠϺϘΡΣΤΥΦΧΨΩ" + gold := "e93d84ec2b22383123be9f713697fb25" + + "338c86e2f7d8d1ddc2d89d332dd9d76c" + if _, err := io.WriteString(c, in); err != nil { + t.Fatalf("could not write to c: %v", err) + } + out := fmt.Sprintf("%x", c.Sum(nil)) + if out != gold { + t.Fatalf("mismatch: got %s, wanted %s", out, gold) + } +} diff --git a/libgo/go/crypto/sha256/sha256.go b/libgo/go/crypto/sha256/sha256.go index d84cebf..74b05b9 100644 --- a/libgo/go/crypto/sha256/sha256.go +++ b/libgo/go/crypto/sha256/sha256.go @@ -137,7 +137,7 @@ func (d0 *digest) Sum(in []byte) []byte { func (d *digest) checkSum() [Size]byte { len := d.len - // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. + // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. var tmp [64]byte tmp[0] = 0x80 if len%64 < 56 { diff --git a/libgo/go/crypto/sha256/sha256_test.go b/libgo/go/crypto/sha256/sha256_test.go index 1d883d3..279cf5a 100644 --- a/libgo/go/crypto/sha256/sha256_test.go +++ b/libgo/go/crypto/sha256/sha256_test.go @@ -2,11 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// SHA256 hash algorithm. See FIPS 180-2. +// SHA256 hash algorithm. See FIPS 180-2. package sha256 import ( + "crypto/rand" "fmt" "io" "testing" @@ -150,6 +151,18 @@ func TestBlockSize(t *testing.T) { } } +// Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match. +func TestBlockGeneric(t *testing.T) { + gen, asm := New().(*digest), New().(*digest) + buf := make([]byte, BlockSize*20) // arbitrary factor + rand.Read(buf) + blockGeneric(gen, buf) + block(asm, buf) + if *gen != *asm { + t.Error("block and blockGeneric resulted in different states") + } +} + var bench = New() var buf = make([]byte, 8192) diff --git a/libgo/go/crypto/sha256/sha256block.go b/libgo/go/crypto/sha256/sha256block.go index ca5efd1..d43bbf0 100644 --- a/libgo/go/crypto/sha256/sha256block.go +++ b/libgo/go/crypto/sha256/sha256block.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !386,!amd64 - // SHA256 block step. // In its own file so that a faster assembly or C version // can be substituted easily. @@ -77,7 +75,7 @@ var _K = []uint32{ 0xc67178f2, } -func block(dig *digest, p []byte) { +func blockGeneric(dig *digest, p []byte) { var w [64]uint32 h0, h1, h2, h3, h4, h5, h6, h7 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] for len(p) >= chunk { diff --git a/libgo/go/crypto/sha256/sha256block_decl.go b/libgo/go/crypto/sha256/sha256block_decl.go index a50c978..e6caff9 100644 --- a/libgo/go/crypto/sha256/sha256block_decl.go +++ b/libgo/go/crypto/sha256/sha256block_decl.go @@ -1,8 +1,8 @@ -// Copyright 2013 The Go Authors. All rights reserved. +// Copyright 2013 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 386 amd64 +// +build 386 amd64 s390x package sha256 diff --git a/libgo/go/crypto/sha256/sha256block_generic.go b/libgo/go/crypto/sha256/sha256block_generic.go new file mode 100644 index 0000000..1a01969 --- /dev/null +++ b/libgo/go/crypto/sha256/sha256block_generic.go @@ -0,0 +1,9 @@ +// Copyright 2016 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 !amd64,!386,!s390x + +package sha256 + +var block = blockGeneric diff --git a/libgo/go/crypto/sha256/sha256block_s390x.go b/libgo/go/crypto/sha256/sha256block_s390x.go new file mode 100644 index 0000000..b7beefe --- /dev/null +++ b/libgo/go/crypto/sha256/sha256block_s390x.go @@ -0,0 +1,12 @@ +// Copyright 2016 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 sha256 + +// featureCheck reports whether the CPU supports the +// SHA256 compute intermediate message digest (KIMD) +// function code. +func featureCheck() bool + +var useAsm = featureCheck() diff --git a/libgo/go/crypto/sha512/fallback_test.go b/libgo/go/crypto/sha512/fallback_test.go new file mode 100644 index 0000000..9024ce6 --- /dev/null +++ b/libgo/go/crypto/sha512/fallback_test.go @@ -0,0 +1,37 @@ +// Copyright 2016 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 s390x + +package sha512 + +import ( + "fmt" + "io" + "testing" +) + +// Tests the fallback code path in case the optimized asm +// implementation cannot be used. +// See also TestBlockGeneric. +func TestGenericPath(t *testing.T) { + if useAsm == false { + t.Skipf("assembly implementation unavailable") + } + useAsm = false + defer func() { useAsm = true }() + c := New() + in := "ΑΒΓΔΕϜΖΗΘΙΚΛΜΝΞΟΠϺϘΡΣΤΥΦΧΨΩ" + gold := "6922e319366d677f34c504af31bfcb29" + + "e531c125ecd08679362bffbd6b6ebfb9" + + "0dcc27dfc1f3d3b16a16c0763cf43b91" + + "40bbf9bbb7233724e9a0c6655b185d76" + if _, err := io.WriteString(c, in); err != nil { + t.Fatalf("could not write to c: %v", err) + } + out := fmt.Sprintf("%x", c.Sum(nil)) + if out != gold { + t.Fatalf("mismatch: got %s, wanted %s", out, gold) + } +} diff --git a/libgo/go/crypto/sha512/sha512.go b/libgo/go/crypto/sha512/sha512.go index e7781fd..5603c90 100644 --- a/libgo/go/crypto/sha512/sha512.go +++ b/libgo/go/crypto/sha512/sha512.go @@ -208,7 +208,7 @@ func (d0 *digest) Sum(in []byte) []byte { } func (d *digest) checkSum() [Size]byte { - // Padding. Add a 1 bit and 0 bits until 112 bytes mod 128. + // Padding. Add a 1 bit and 0 bits until 112 bytes mod 128. len := d.len var tmp [128]byte tmp[0] = 0x80 diff --git a/libgo/go/crypto/sha512/sha512_test.go b/libgo/go/crypto/sha512/sha512_test.go index 04b3d4a..a3a136a 100644 --- a/libgo/go/crypto/sha512/sha512_test.go +++ b/libgo/go/crypto/sha512/sha512_test.go @@ -2,11 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// SHA512 hash algorithm. See FIPS 180-4. +// SHA512 hash algorithm. See FIPS 180-4. package sha512 import ( + "crypto/rand" "encoding/hex" "hash" "io" @@ -304,6 +305,18 @@ func TestBlockSize(t *testing.T) { } } +// Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match. +func TestBlockGeneric(t *testing.T) { + gen, asm := New().(*digest), New().(*digest) + buf := make([]byte, BlockSize*20) // arbitrary factor + rand.Read(buf) + blockGeneric(gen, buf) + block(asm, buf) + if *gen != *asm { + t.Error("block and blockGeneric resulted in different states") + } +} + var bench = New() var buf = make([]byte, 8192) diff --git a/libgo/go/crypto/sha512/sha512block.go b/libgo/go/crypto/sha512/sha512block.go index 648ae8f..42e8d19 100644 --- a/libgo/go/crypto/sha512/sha512block.go +++ b/libgo/go/crypto/sha512/sha512block.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !amd64 - // SHA512 block step. // In its own file so that a faster assembly or C version // can be substituted easily. @@ -93,7 +91,7 @@ var _K = []uint64{ 0x6c44198c4a475817, } -func block(dig *digest, p []byte) { +func blockGeneric(dig *digest, p []byte) { var w [80]uint64 h0, h1, h2, h3, h4, h5, h6, h7 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] for len(p) >= chunk { diff --git a/libgo/go/crypto/sha512/sha512block_decl.go b/libgo/go/crypto/sha512/sha512block_decl.go index bef99de..47d656a 100644 --- a/libgo/go/crypto/sha512/sha512block_decl.go +++ b/libgo/go/crypto/sha512/sha512block_decl.go @@ -1,8 +1,8 @@ -// Copyright 2013 The Go Authors. All rights reserved. +// Copyright 2013 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 amd64 +// +build amd64 s390x package sha512 diff --git a/libgo/go/crypto/sha512/sha512block_generic.go b/libgo/go/crypto/sha512/sha512block_generic.go new file mode 100644 index 0000000..2c691ba --- /dev/null +++ b/libgo/go/crypto/sha512/sha512block_generic.go @@ -0,0 +1,9 @@ +// Copyright 2016 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 !amd64,!s390x + +package sha512 + +var block = blockGeneric diff --git a/libgo/go/crypto/sha512/sha512block_s390x.go b/libgo/go/crypto/sha512/sha512block_s390x.go new file mode 100644 index 0000000..f05dc18 --- /dev/null +++ b/libgo/go/crypto/sha512/sha512block_s390x.go @@ -0,0 +1,12 @@ +// Copyright 2016 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 sha512 + +// featureCheck reports whether the CPU supports the +// SHA512 compute intermediate message digest (KIMD) +// function code. +func featureCheck() bool + +var useAsm = featureCheck() diff --git a/libgo/go/crypto/subtle/constant_time.go b/libgo/go/crypto/subtle/constant_time.go index 6f80e7c..11312b8 100644 --- a/libgo/go/crypto/subtle/constant_time.go +++ b/libgo/go/crypto/subtle/constant_time.go @@ -6,7 +6,7 @@ // code but require careful thought to use correctly. package subtle -// ConstantTimeCompare returns 1 iff the two slices, x +// ConstantTimeCompare returns 1 if and only if the two slices, x // and y, have equal contents. The time taken is a function of the length of // the slices and is independent of the contents. func ConstantTimeCompare(x, y []byte) int { diff --git a/libgo/go/crypto/tls/alert.go b/libgo/go/crypto/tls/alert.go index 3de4834..9cf9922 100644 --- a/libgo/go/crypto/tls/alert.go +++ b/libgo/go/crypto/tls/alert.go @@ -69,9 +69,9 @@ var alertText = map[alert]string{ func (e alert) String() string { s, ok := alertText[e] if ok { - return s + return "tls: " + s } - return "alert(" + strconv.Itoa(int(e)) + ")" + return "tls: alert(" + strconv.Itoa(int(e)) + ")" } func (e alert) Error() string { diff --git a/libgo/go/crypto/tls/cipher_suites.go b/libgo/go/crypto/tls/cipher_suites.go index 869ffa5..e69f5f96 100644 --- a/libgo/go/crypto/tls/cipher_suites.go +++ b/libgo/go/crypto/tls/cipher_suites.go @@ -74,7 +74,7 @@ type cipherSuite struct { var cipherSuites = []*cipherSuite{ // Ciphersuite order is chosen so that ECDHE comes before plain RSA - // and RC4 comes before AES (because of the Lucky13 attack). + // and RC4 comes before AES-CBC (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}, @@ -261,8 +261,10 @@ func mutualCipherSuite(have []uint16, want uint16) *cipherSuite { return nil } -// A list of the possible cipher suite ids. Taken from -// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml +// 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 const ( TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005 TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000a @@ -284,6 +286,6 @@ const ( // 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. + // https://tools.ietf.org/html/rfc7507. TLS_FALLBACK_SCSV uint16 = 0x5600 ) diff --git a/libgo/go/crypto/tls/common.go b/libgo/go/crypto/tls/common.go index c68ebfe..9fc7420 100644 --- a/libgo/go/crypto/tls/common.go +++ b/libgo/go/crypto/tls/common.go @@ -48,6 +48,7 @@ const ( // TLS handshake message types. const ( + typeHelloRequest uint8 = 0 typeClientHello uint8 = 1 typeServerHello uint8 = 2 typeNewSessionTicket uint8 = 4 @@ -114,7 +115,7 @@ const ( 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. + // See RFC 4492 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. @@ -238,6 +239,33 @@ type ClientHelloInfo struct { SupportedPoints []uint8 } +// RenegotiationSupport enumerates the different levels of support for TLS +// renegotiation. TLS renegotiation is the act of performing subsequent +// handshakes on a connection after the first. This significantly complicates +// the state machine and has been the source of numerous, subtle security +// issues. Initiating a renegotiation is not supported, but support for +// accepting renegotiation requests may be enabled. +// +// Even when enabled, the server may not change its identity between handshakes +// (i.e. the leaf certificate must be the same). Additionally, concurrent +// handshake and application data flow is not permitted so renegotiation can +// only be used with protocols that synchronise with the renegotiation, such as +// HTTPS. +type RenegotiationSupport int + +const ( + // RenegotiateNever disables renegotiation. + RenegotiateNever RenegotiationSupport = iota + + // RenegotiateOnceAsClient allows a remote server to request + // renegotiation once per connection. + RenegotiateOnceAsClient + + // RenegotiateFreelyAsClient allows a remote server to repeatedly + // request renegotiation. + RenegotiateFreelyAsClient +) + // 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 @@ -349,6 +377,16 @@ type Config struct { // be used. CurvePreferences []CurveID + // DynamicRecordSizingDisabled disables adaptive sizing of TLS records. + // When true, the largest possible TLS record size is always used. When + // false, the size of TLS records may be adjusted in an attempt to + // improve latency. + DynamicRecordSizingDisabled bool + + // Renegotiation controls what types of renegotiation are supported. + // The default, none, is correct for the vast majority of applications. + Renegotiation RenegotiationSupport + serverInitOnce sync.Once // guards calling (*Config).serverInit // mutex protects sessionTicketKeys @@ -384,6 +422,33 @@ func ticketKeyFromBytes(b [32]byte) (key ticketKey) { return key } +// clone returns a copy of c. Only the exported fields are copied. +func (c *Config) clone() *Config { + return &Config{ + Rand: c.Rand, + Time: c.Time, + Certificates: c.Certificates, + NameToCertificate: c.NameToCertificate, + GetCertificate: c.GetCertificate, + RootCAs: c.RootCAs, + NextProtos: c.NextProtos, + ServerName: c.ServerName, + ClientAuth: c.ClientAuth, + ClientCAs: c.ClientCAs, + InsecureSkipVerify: c.InsecureSkipVerify, + CipherSuites: c.CipherSuites, + PreferServerCipherSuites: c.PreferServerCipherSuites, + SessionTicketsDisabled: c.SessionTicketsDisabled, + SessionTicketKey: c.SessionTicketKey, + ClientSessionCache: c.ClientSessionCache, + MinVersion: c.MinVersion, + MaxVersion: c.MaxVersion, + CurvePreferences: c.CurvePreferences, + DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled, + Renegotiation: c.Renegotiation, + } +} + func (c *Config) serverInit() { if c.SessionTicketsDisabled { return @@ -510,7 +575,7 @@ func (c *Config) getCertificate(clientHello *ClientHelloInfo) (*Certificate, err } if len(c.Certificates) == 0 { - return nil, errors.New("crypto/tls: no certificates configured") + return nil, errors.New("tls: no certificates configured") } if len(c.Certificates) == 1 || c.NameToCertificate == nil { @@ -584,13 +649,6 @@ type Certificate struct { Leaf *x509.Certificate } -// A TLS record. -type record struct { - contentType recordType - major, minor uint8 - payload []byte -} - type handshakeMessage interface { marshal() []byte unmarshal([]byte) bool diff --git a/libgo/go/crypto/tls/conn.go b/libgo/go/crypto/tls/conn.go index 0377568..87bef23d 100644 --- a/libgo/go/crypto/tls/conn.go +++ b/libgo/go/crypto/tls/conn.go @@ -28,34 +28,60 @@ type Conn struct { isClient bool // constant after handshake; protected by handshakeMutex - handshakeMutex sync.Mutex // handshakeMutex < in.Mutex, out.Mutex, errMutex - 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 // handshakeMutex < in.Mutex, out.Mutex, errMutex + 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 transfering + // application data (i.e. is not currently processing a handshake). handshakeComplete bool - didResume bool // whether this connection was a session resumption - cipherSuite uint16 - ocspResponse []byte // stapled OCSP response - scts [][]byte // signed certificate timestamps from server - peerCertificates []*x509.Certificate + // handshakes counts the number of handshakes performed on the + // connection so far. If renegotiation is disabled then this is either + // zero or one. + handshakes int + didResume bool // whether this connection was a session resumption + cipherSuite uint16 + ocspResponse []byte // stapled OCSP response + scts [][]byte // signed certificate timestamps from server + peerCertificates []*x509.Certificate // verifiedChains contains the certificate chains that we built, as // opposed to the ones presented by the server. verifiedChains [][]*x509.Certificate // serverName contains the server name indicated by the client, if any. serverName string - // firstFinished contains the first Finished hash sent during the - // handshake. This is the "tls-unique" channel binding value. - firstFinished [12]byte + // secureRenegotiation is true if the server echoed the secure + // renegotiation extension. (This is meaningless as a server because + // renegotiation is not supported in that case.) + secureRenegotiation bool + + // clientFinishedIsFirst is true if the client sent the first Finished + // message during the most recent handshake. This is recorded because + // the first transmitted Finished message is the tls-unique + // channel-binding value. + clientFinishedIsFirst bool + // clientFinished and serverFinished contain the Finished message sent + // by the client or server in the most recent handshake. This is + // retained to support the renegotiation extension and tls-unique + // channel-binding. + clientFinished [12]byte + serverFinished [12]byte clientProtocol string clientProtocolFallback bool // input/output - in, out halfConn // in.Mutex < out.Mutex - 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 + in, out halfConn // in.Mutex < out.Mutex + 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 + buffering bool // whether records are buffered in sendBuf + sendBuf []byte // a buffer of records waiting to be sent + + // bytesSent counts the bytes of application data sent. + // packetsSent counts packets. + bytesSent int64 + packetsSent int64 // activeCall is an atomic int32; the low bit is whether Close has // been called. the rest of the bits are the number of goroutines @@ -124,13 +150,6 @@ func (hc *halfConn) setErrorLocked(err error) error { return err } -func (hc *halfConn) error() error { - hc.Lock() - err := hc.err - hc.Unlock() - return err -} - // prepareCipherSpec sets the encryption and MAC states // that a subsequent changeCipherSpec will use. func (hc *halfConn) prepareCipherSpec(version uint16, cipher interface{}, mac macFunction) { @@ -170,13 +189,6 @@ func (hc *halfConn) incSeq() { panic("TLS: sequence number wraparound") } -// resetSeq resets the sequence number to zero. -func (hc *halfConn) resetSeq() { - for i := range hc.seq { - hc.seq[i] = 0 - } -} - // removePadding returns an unpadded slice, in constant time, which is a prefix // of the input. It also returns a byte which is equal to 255 if the padding // was valid and 0 otherwise. See RFC 2246, section 6.2.3.2 @@ -535,7 +547,7 @@ func (c *Conn) newRecordHeaderError(msg string) (err RecordHeaderError) { func (c *Conn) readRecord(want recordType) error { // Caller must be in sync with connection: // handshake data if handshake not yet completed, - // else application data. (We don't support renegotiation.) + // else application data. switch want { default: c.sendAlert(alertInternalError) @@ -543,12 +555,12 @@ func (c *Conn) readRecord(want recordType) error { case recordTypeHandshake, recordTypeChangeCipherSpec: if c.handshakeComplete { c.sendAlert(alertInternalError) - return c.in.setErrorLocked(errors.New("tls: handshake or ChangeCipherSpec requested after handshake complete")) + return c.in.setErrorLocked(errors.New("tls: handshake or ChangeCipherSpec requested while not in handshake")) } case recordTypeApplicationData: if !c.handshakeComplete { c.sendAlert(alertInternalError) - return c.in.setErrorLocked(errors.New("tls: application data record requested before handshake complete")) + return c.in.setErrorLocked(errors.New("tls: application data record requested while in handshake")) } } @@ -672,7 +684,7 @@ Again: case recordTypeHandshake: // TODO(rsc): Should at least pick off connection close. - if typ != want { + if typ != want && !(c.isClient && c.config.Renegotiation != RenegotiateNever) { return c.in.setErrorLocked(c.sendAlert(alertNoRenegotiation)) } c.hand.Write(data) @@ -694,12 +706,14 @@ func (c *Conn) sendAlertLocked(err alert) error { c.tmp[0] = alertLevelError } c.tmp[1] = byte(err) - c.writeRecord(recordTypeAlert, c.tmp[0:2]) - // closeNotify is a special case in that it isn't an error: - if err != alertCloseNotify { - return c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err}) + + _, writeErr := c.writeRecordLocked(recordTypeAlert, c.tmp[0:2]) + if err == alertCloseNotify { + // closeNotify is a special case in that it isn't an error. + return writeErr } - return nil + + return c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err}) } // sendAlert sends a TLS alert message. @@ -710,16 +724,120 @@ func (c *Conn) sendAlert(err alert) error { return c.sendAlertLocked(err) } -// writeRecord writes a TLS record with the given type and payload -// to the connection and updates the record layer state. +const ( + // tcpMSSEstimate is a conservative estimate of the TCP maximum segment + // size (MSS). A constant is used, rather than querying the kernel for + // the actual MSS, to avoid complexity. The value here is the IPv6 + // minimum MTU (1280 bytes) minus the overhead of an IPv6 header (40 + // bytes) and a TCP header with timestamps (32 bytes). + tcpMSSEstimate = 1208 + + // recordSizeBoostThreshold is the number of bytes of application data + // sent after which the TLS record size will be increased to the + // maximum. + recordSizeBoostThreshold = 128 * 1024 +) + +// maxPayloadSizeForWrite returns the maximum TLS payload size to use for the +// next application data record. There is the following trade-off: +// +// - For latency-sensitive applications, such as web browsing, each TLS +// record should fit in one TCP segment. +// - For throughput-sensitive applications, such as large file transfers, +// larger TLS records better amortize framing and encryption overheads. +// +// A simple heuristic that works well in practice is to use small records for +// the first 1MB of data, then use larger records for subsequent data, and +// reset back to smaller records after the connection becomes idle. See "High +// Performance Web Networking", Chapter 4, or: +// https://www.igvita.com/2013/10/24/optimizing-tls-record-size-and-buffering-latency/ +// +// 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 + } + + if c.bytesSent >= recordSizeBoostThreshold { + return maxPlaintext + } + + // Subtract TLS overheads to get the maximum payload size. + macSize := 0 + if c.out.mac != nil { + macSize = c.out.mac.Size() + } + + payloadBytes := tcpMSSEstimate - recordHeaderLen - explicitIVLen + if c.out.cipher != nil { + switch ciph := c.out.cipher.(type) { + case cipher.Stream: + payloadBytes -= macSize + case cipher.AEAD: + payloadBytes -= ciph.Overhead() + case cbcMode: + blockSize := ciph.BlockSize() + // The payload must fit in a multiple of blockSize, with + // room for at least one padding byte. + payloadBytes = (payloadBytes & ^(blockSize - 1)) - 1 + // The MAC is appended before padding so affects the + // payload size directly. + payloadBytes -= macSize + default: + panic("unknown cipher type") + } + } + + // Allow packet growth in arithmetic progression up to max. + pkt := c.packetsSent + c.packetsSent++ + if pkt > 1000 { + return maxPlaintext // avoid overflow in multiply below + } + + n := payloadBytes * int(pkt+1) + if n > maxPlaintext { + n = maxPlaintext + } + return n +} + // c.out.Mutex <= L. -func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) { +func (c *Conn) write(data []byte) (int, error) { + if c.buffering { + c.sendBuf = append(c.sendBuf, data...) + return len(data), nil + } + + n, err := c.conn.Write(data) + c.bytesSent += int64(n) + return n, err +} + +func (c *Conn) flush() (int, error) { + if len(c.sendBuf) == 0 { + return 0, nil + } + + n, err := c.conn.Write(c.sendBuf) + c.bytesSent += int64(n) + c.sendBuf = nil + c.buffering = false + return n, err +} + +// 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) + + var n int for len(data) > 0 { - m := len(data) - if m > maxPlaintext { - m = maxPlaintext - } explicitIVLen := 0 explicitIVIsSeq := false @@ -742,6 +860,10 @@ func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) { explicitIVIsSeq = true } } + m := len(data) + if maxPayload := c.maxPayloadSizeForWrite(typ, explicitIVLen); m > maxPayload { + m = maxPayload + } b.resize(recordHeaderLen + explicitIVLen + m) b.data[0] = byte(typ) vers := c.vers @@ -759,34 +881,37 @@ func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) { if explicitIVIsSeq { copy(explicitIV, c.out.seq[:]) } else { - if _, err = io.ReadFull(c.config.rand(), explicitIV); err != nil { - break + if _, err := io.ReadFull(c.config.rand(), explicitIV); err != nil { + return n, err } } } copy(b.data[recordHeaderLen+explicitIVLen:], data) c.out.encrypt(b, explicitIVLen) - _, err = c.conn.Write(b.data) - if err != nil { - break + if _, err := c.write(b.data); err != nil { + return n, err } n += m data = data[m:] } - c.out.freeBlock(b) if typ == recordTypeChangeCipherSpec { - err = c.out.changeCipherSpec() - if err != nil { - // Cannot call sendAlert directly, - // because we already hold c.out.Mutex. - c.tmp[0] = alertLevelError - c.tmp[1] = byte(err.(alert)) - c.writeRecord(recordTypeAlert, c.tmp[0:2]) - return n, c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err}) + if err := c.out.changeCipherSpec(); err != nil { + return n, c.sendAlertLocked(err.(alert)) } } - return + + return n, nil +} + +// 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() + + return c.writeRecordLocked(typ, data) } // readHandshake reads the next handshake message from @@ -805,7 +930,8 @@ func (c *Conn) readHandshake() (interface{}, error) { data := c.hand.Bytes() n := int(data[1])<<16 | int(data[2])<<8 | int(data[3]) if n > maxHandshake { - return nil, c.in.setErrorLocked(c.sendAlert(alertInternalError)) + c.sendAlertLocked(alertInternalError) + return nil, c.in.setErrorLocked(fmt.Errorf("tls: handshake message of length %d bytes exceeds maximum of %d bytes", n, maxHandshake)) } for c.hand.Len() < 4+n { if err := c.in.err; err != nil { @@ -818,6 +944,8 @@ func (c *Conn) readHandshake() (interface{}, error) { data = c.hand.Next(4 + n) var m handshakeMessage switch data[0] { + case typeHelloRequest: + m = new(helloRequestMsg) case typeClientHello: m = new(clientHelloMsg) case typeServerHello: @@ -861,7 +989,7 @@ func (c *Conn) readHandshake() (interface{}, error) { return m, nil } -var errClosed = errors.New("crypto/tls: use of closed connection") +var errClosed = errors.New("tls: use of closed connection") // Write writes data to the connection. func (c *Conn) Write(b []byte) (int, error) { @@ -904,7 +1032,7 @@ func (c *Conn) Write(b []byte) (int, error) { var m int if len(b) > 1 && c.vers <= VersionTLS10 { if _, ok := c.out.cipher.(cipher.BlockMode); ok { - n, err := c.writeRecord(recordTypeApplicationData, b[:1]) + n, err := c.writeRecordLocked(recordTypeApplicationData, b[:1]) if err != nil { return n, c.out.setErrorLocked(err) } @@ -912,10 +1040,52 @@ func (c *Conn) Write(b []byte) (int, error) { } } - n, err := c.writeRecord(recordTypeApplicationData, b) + n, err := c.writeRecordLocked(recordTypeApplicationData, b) return n + m, c.out.setErrorLocked(err) } +// handleRenegotiation processes a HelloRequest handshake message. +// c.in.Mutex <= L +func (c *Conn) handleRenegotiation() error { + msg, err := c.readHandshake() + if err != nil { + return err + } + + _, ok := msg.(*helloRequestMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return alertUnexpectedMessage + } + + if !c.isClient { + return c.sendAlert(alertNoRenegotiation) + } + + switch c.config.Renegotiation { + case RenegotiateNever: + return c.sendAlert(alertNoRenegotiation) + case RenegotiateOnceAsClient: + if c.handshakes > 1 { + return c.sendAlert(alertNoRenegotiation) + } + case RenegotiateFreelyAsClient: + // Ok. + default: + c.sendAlert(alertInternalError) + return errors.New("tls: unknown Renegotiation value") + } + + c.handshakeMutex.Lock() + defer c.handshakeMutex.Unlock() + + c.handshakeComplete = false + if c.handshakeErr = c.clientHandshake(); c.handshakeErr == nil { + c.handshakes++ + } + return c.handshakeErr +} + // Read can be made to time out and return a net.Error with Timeout() == true // after a fixed time limit; see SetDeadline and SetReadDeadline. func (c *Conn) Read(b []byte) (n int, err error) { @@ -940,6 +1110,13 @@ func (c *Conn) Read(b []byte) (n int, err error) { // Soft error, like EAGAIN return 0, err } + if c.hand.Len() > 0 { + // We received handshake bytes, indicating the + // start of a renegotiation. + if err := c.handleRenegotiation(); err != nil { + return 0, err + } + } } if err := c.in.err; err != nil { return 0, err @@ -1020,13 +1197,35 @@ func (c *Conn) Close() 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 take c.handshakeMutex first and, if we find that a handshake + // is needed, then we unlock, acquire c.in and c.handshakeMutex in the + // correct order, and check again. c.handshakeMutex.Lock() defer c.handshakeMutex.Unlock() - if err := c.handshakeErr; err != nil { - return err - } - if c.handshakeComplete { - return nil + + for i := 0; i < 2; i++ { + if i == 1 { + c.handshakeMutex.Unlock() + c.in.Lock() + defer c.in.Unlock() + c.handshakeMutex.Lock() + } + + if err := c.handshakeErr; err != nil { + return err + } + if c.handshakeComplete { + return nil + } } if c.isClient { @@ -1034,6 +1233,9 @@ func (c *Conn) Handshake() error { } else { c.handshakeErr = c.serverHandshake() } + if c.handshakeErr == nil { + c.handshakes++ + } return c.handshakeErr } @@ -1056,7 +1258,11 @@ func (c *Conn) ConnectionState() ConnectionState { state.SignedCertificateTimestamps = c.scts state.OCSPResponse = c.ocspResponse if !c.didResume { - state.TLSUnique = c.firstFinished[:] + if c.clientFinishedIsFirst { + state.TLSUnique = c.clientFinished[:] + } else { + state.TLSUnique = c.serverFinished[:] + } } } @@ -1073,7 +1279,7 @@ func (c *Conn) OCSPResponse() []byte { } // VerifyHostname checks that the peer certificate chain is valid for -// connecting to host. If so, it returns nil; if not, it returns an error +// connecting to host. If so, it returns nil; if not, it returns an error // describing the problem. func (c *Conn) VerifyHostname(host string) error { c.handshakeMutex.Lock() diff --git a/libgo/go/crypto/tls/conn_test.go b/libgo/go/crypto/tls/conn_test.go index ec802ca..5cff7e7 100644 --- a/libgo/go/crypto/tls/conn_test.go +++ b/libgo/go/crypto/tls/conn_test.go @@ -5,6 +5,9 @@ package tls import ( + "bytes" + "io" + "net" "testing" ) @@ -116,3 +119,125 @@ func TestCertificateSelection(t *testing.T) { t.Errorf("foo.bar.baz.example.com returned certificate %d, not 0", n) } } + +// Run with multiple crypto configs to test the logic for computing TLS record overheads. +func runDynamicRecordSizingTest(t *testing.T, config *Config) { + clientConn, serverConn := net.Pipe() + + serverConfig := config.clone() + serverConfig.DynamicRecordSizingDisabled = false + tlsConn := Server(serverConn, serverConfig) + + recordSizesChan := make(chan []int, 1) + go func() { + // This goroutine performs a TLS handshake over clientConn and + // then reads TLS records until EOF. It writes a slice that + // contains all the record sizes to recordSizesChan. + defer close(recordSizesChan) + defer clientConn.Close() + + tlsConn := Client(clientConn, config) + if err := tlsConn.Handshake(); err != nil { + t.Errorf("Error from client handshake: %s", err) + return + } + + var recordHeader [recordHeaderLen]byte + var record []byte + var recordSizes []int + + for { + n, err := clientConn.Read(recordHeader[:]) + if err == io.EOF { + break + } + if err != nil || n != len(recordHeader) { + t.Errorf("Error from client read: %s", err) + return + } + + length := int(recordHeader[3])<<8 | int(recordHeader[4]) + if len(record) < length { + record = make([]byte, length) + } + + n, err = clientConn.Read(record[:length]) + if err != nil || n != length { + t.Errorf("Error from client read: %s", err) + return + } + + // The last record will be a close_notify alert, which + // we don't wish to record. + if recordType(recordHeader[0]) == recordTypeApplicationData { + recordSizes = append(recordSizes, recordHeaderLen+length) + } + } + + recordSizesChan <- recordSizes + }() + + if err := tlsConn.Handshake(); err != nil { + t.Fatalf("Error from server handshake: %s", err) + } + + // The server writes these plaintexts in order. + plaintext := bytes.Join([][]byte{ + bytes.Repeat([]byte("x"), recordSizeBoostThreshold), + bytes.Repeat([]byte("y"), maxPlaintext*2), + bytes.Repeat([]byte("z"), maxPlaintext), + }, nil) + + if _, err := tlsConn.Write(plaintext); err != nil { + t.Fatalf("Error from server write: %s", err) + } + if err := tlsConn.Close(); err != nil { + t.Fatalf("Error from server close: %s", err) + } + + recordSizes := <-recordSizesChan + if recordSizes == nil { + t.Fatalf("Client encountered an error") + } + + // Drop the size of last record, which is likely to be truncated. + recordSizes = recordSizes[:len(recordSizes)-1] + + // recordSizes should contain a series of records smaller than + // tcpMSSEstimate followed by some larger than maxPlaintext. + seenLargeRecord := false + for i, size := range recordSizes { + if !seenLargeRecord { + if size > (i+1)*tcpMSSEstimate { + t.Fatalf("Record #%d has size %d, which is too large too soon", i, size) + } + if size >= maxPlaintext { + seenLargeRecord = true + } + } else if size <= maxPlaintext { + t.Fatalf("Record #%d has size %d but should be full sized", i, size) + } + } + + if !seenLargeRecord { + t.Fatalf("No large records observed") + } +} + +func TestDynamicRecordSizingWithStreamCipher(t *testing.T) { + config := testConfig.clone() + config.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA} + runDynamicRecordSizingTest(t, config) +} + +func TestDynamicRecordSizingWithCBC(t *testing.T) { + config := testConfig.clone() + config.CipherSuites = []uint16{TLS_RSA_WITH_AES_256_CBC_SHA} + runDynamicRecordSizingTest(t, config) +} + +func TestDynamicRecordSizingWithAEAD(t *testing.T) { + config := testConfig.clone() + config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256} + runDynamicRecordSizingTest(t, config) +} diff --git a/libgo/go/crypto/tls/handshake_client.go b/libgo/go/crypto/tls/handshake_client.go index 3c996ac..f789e6f 100644 --- a/libgo/go/crypto/tls/handshake_client.go +++ b/libgo/go/crypto/tls/handshake_client.go @@ -16,6 +16,7 @@ import ( "io" "net" "strconv" + "strings" ) type clientHandshakeState struct { @@ -28,11 +29,16 @@ type clientHandshakeState struct { session *ClientSessionState } +// c.out.Mutex <= L; c.handshakeMutex <= L. func (c *Conn) clientHandshake() error { if c.config == nil { c.config = defaultConfig() } + // This may be a renegotiation handshake, in which case some fields + // need to be reset. + c.didResume = false + if len(c.config.ServerName) == 0 && !c.config.InsecureSkipVerify { return errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config") } @@ -49,25 +55,22 @@ func (c *Conn) clientHandshake() error { 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: hostnameInSNI(c.config.ServerName), + supportedCurves: c.config.curvePreferences(), + supportedPoints: []uint8{pointFormatUncompressed}, + nextProtoNeg: len(c.config.NextProtos) > 0, + secureRenegotiationSupported: true, + alpnProtocols: c.config.NextProtos, } - 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, + if c.handshakes > 0 { + hello.secureRenegotiation = c.clientFinished[:] } possibleCipherSuites := c.config.cipherSuites() @@ -108,7 +111,12 @@ NextCipherSuite: if sessionCache != nil { hello.ticketSupported = true + } + // Session resumption is not allowed if renegotiating because + // renegotiation is primarily used to allow a client to send a client + // certificate, which would be skipped if session resumption occured. + if sessionCache != nil && c.handshakes == 0 { // Try to resume a previously negotiated TLS session, if // available. cacheKey = clientSessionCacheKey(c.conn.RemoteAddr(), c.config) @@ -144,7 +152,9 @@ NextCipherSuite: } } - c.writeRecord(recordTypeHandshake, hello.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, hello.marshal()); err != nil { + return err + } msg, err := c.readHandshake() if err != nil { @@ -196,6 +206,7 @@ NextCipherSuite: hs.finishedHash.Write(hs.hello.marshal()) hs.finishedHash.Write(hs.serverHello.marshal()) + c.buffering = true if isResume { if err := hs.establishKeys(); err != nil { return err @@ -203,10 +214,14 @@ NextCipherSuite: if err := hs.readSessionTicket(); err != nil { return err } - if err := hs.readFinished(c.firstFinished[:]); err != nil { + if err := hs.readFinished(c.serverFinished[:]); err != nil { + return err + } + c.clientFinishedIsFirst = false + if err := hs.sendFinished(c.clientFinished[:]); err != nil { return err } - if err := hs.sendFinished(nil); err != nil { + if _, err := c.flush(); err != nil { return err } } else { @@ -216,13 +231,17 @@ NextCipherSuite: if err := hs.establishKeys(); err != nil { return err } - if err := hs.sendFinished(c.firstFinished[:]); err != nil { + if err := hs.sendFinished(c.clientFinished[:]); err != nil { return err } + if _, err := c.flush(); err != nil { + return err + } + c.clientFinishedIsFirst = true if err := hs.readSessionTicket(); err != nil { return err } - if err := hs.readFinished(nil); err != nil { + if err := hs.readFinished(c.serverFinished[:]); err != nil { return err } } @@ -251,47 +270,62 @@ func (hs *clientHandshakeState) doFullHandshake() error { } 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()) + if c.handshakes == 0 { + // If this is the first handshake on a connection, process and + // (optionally) verify the server's certificates. + 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 } - 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(), - } + 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 + 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 } - 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) } - } - 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 + } else { + // This is a renegotiation handshake. We require that the + // server's identity (i.e. leaf certificate) is unchanged and + // thus any previous trust decision is still valid. + // + // See https://mitls.org/pages/attacks/3SHAKE for the + // motivation behind this requirement. + if !bytes.Equal(c.peerCertificates[0].Raw, certMsg.certificates[0]) { + c.sendAlert(alertBadCertificate) + return errors.New("tls: server's identity changed during renegotiation") + } } - c.peerCertificates = certs - if hs.serverHello.ocspStapling { msg, err = c.readHandshake() if err != nil { @@ -319,7 +353,7 @@ func (hs *clientHandshakeState) doFullHandshake() error { skx, ok := msg.(*serverKeyExchangeMsg) if ok { hs.finishedHash.Write(skx.marshal()) - err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, certs[0], skx) + err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, c.peerCertificates[0], skx) if err != nil { c.sendAlert(alertUnexpectedMessage) return err @@ -425,17 +459,21 @@ func (hs *clientHandshakeState) doFullHandshake() error { certMsg.certificates = chainToSend.Certificate } hs.finishedHash.Write(certMsg.marshal()) - c.writeRecord(recordTypeHandshake, certMsg.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil { + return err + } } - preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, certs[0]) + preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, c.peerCertificates[0]) if err != nil { c.sendAlert(alertInternalError) return err } if ckx != nil { hs.finishedHash.Write(ckx.marshal()) - c.writeRecord(recordTypeHandshake, ckx.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, ckx.marshal()); err != nil { + return err + } } if chainToSend != nil { @@ -477,7 +515,9 @@ func (hs *clientHandshakeState) doFullHandshake() error { } hs.finishedHash.Write(certVerify.marshal()) - c.writeRecord(recordTypeHandshake, certVerify.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, certVerify.marshal()); err != nil { + return err + } } hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random) @@ -524,6 +564,24 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) { return false, errors.New("tls: server selected unsupported compression format") } + if c.handshakes == 0 && hs.serverHello.secureRenegotiationSupported { + c.secureRenegotiation = true + if len(hs.serverHello.secureRenegotiation) != 0 { + c.sendAlert(alertHandshakeFailure) + return false, errors.New("tls: initial handshake had non-empty renegotiation extension") + } + } + + if c.handshakes > 0 && c.secureRenegotiation { + var expectedSecureRenegotiation [24]byte + copy(expectedSecureRenegotiation[:], c.clientFinished[:]) + copy(expectedSecureRenegotiation[12:], c.serverFinished[:]) + if !bytes.Equal(hs.serverHello.secureRenegotiation, expectedSecureRenegotiation[:]) { + c.sendAlert(alertHandshakeFailure) + return false, errors.New("tls: incorrect renegotiation extension contents") + } + } + clientDidNPN := hs.hello.nextProtoNeg clientDidALPN := len(hs.hello.alpnProtocols) > 0 serverHasNPN := hs.serverHello.nextProtoNeg @@ -531,17 +589,17 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) { if !clientDidNPN && serverHasNPN { c.sendAlert(alertHandshakeFailure) - return false, errors.New("server advertised unrequested NPN extension") + return false, errors.New("tls: server advertised unrequested NPN extension") } if !clientDidALPN && serverHasALPN { c.sendAlert(alertHandshakeFailure) - return false, errors.New("server advertised unrequested ALPN extension") + return false, errors.New("tls: server advertised unrequested ALPN extension") } if serverHasNPN && serverHasALPN { c.sendAlert(alertHandshakeFailure) - return false, errors.New("server advertised both NPN and ALPN extensions") + return false, errors.New("tls: server advertised both NPN and ALPN extensions") } if serverHasALPN { @@ -550,22 +608,33 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) { } 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 + if !hs.serverResumedSession() { + return false, nil + } + + if hs.session.vers != c.vers { + c.sendAlert(alertHandshakeFailure) + return false, errors.New("tls: server resumed a session with a different version") + } + + if hs.session.cipherSuite != hs.suite.id { + c.sendAlert(alertHandshakeFailure) + return false, errors.New("tls: server resumed a session with a different cipher suite") } - return false, nil + + // 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 } func (hs *clientHandshakeState) readFinished(out []byte) error { c := hs.c c.readRecord(recordTypeChangeCipherSpec) - if err := c.in.error(); err != nil { - return err + if c.in.err != nil { + return c.in.err } msg, err := c.readHandshake() @@ -621,7 +690,9 @@ func (hs *clientHandshakeState) readSessionTicket() error { func (hs *clientHandshakeState) sendFinished(out []byte) error { c := hs.c - c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) + if _, err := c.writeRecord(recordTypeChangeCipherSpec, []byte{1}); err != nil { + return err + } if hs.serverHello.nextProtoNeg { nextProto := new(nextProtoMsg) proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.nextProtos) @@ -630,13 +701,17 @@ func (hs *clientHandshakeState) sendFinished(out []byte) error { c.clientProtocolFallback = fallback hs.finishedHash.Write(nextProto.marshal()) - c.writeRecord(recordTypeHandshake, nextProto.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, nextProto.marshal()); err != nil { + return err + } } finished := new(finishedMsg) finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret) hs.finishedHash.Write(finished.marshal()) - c.writeRecord(recordTypeHandshake, finished.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, finished.marshal()); err != nil { + return err + } copy(out, finished.verifyData) return nil } @@ -665,3 +740,23 @@ func mutualProtocol(protos, preferenceProtos []string) (string, bool) { return protos[0], true } + +// hostnameInSNI converts name into an approriate hostname for SNI. +// Literal IP addresses and absolute FQDNs are not permitted as SNI values. +// See https://tools.ietf.org/html/rfc6066#section-3. +func hostnameInSNI(name string) string { + host := name + if len(host) > 0 && host[0] == '[' && host[len(host)-1] == ']' { + host = host[1 : len(host)-1] + } + if i := strings.LastIndex(host, "%"); i > 0 { + host = host[:i] + } + if net.ParseIP(host) != nil { + return "" + } + if len(name) > 0 && name[len(name)-1] == '.' { + name = name[:len(name)-1] + } + return name +} diff --git a/libgo/go/crypto/tls/handshake_client_test.go b/libgo/go/crypto/tls/handshake_client_test.go index f78cc46..ce987f1 100644 --- a/libgo/go/crypto/tls/handshake_client_test.go +++ b/libgo/go/crypto/tls/handshake_client_test.go @@ -12,6 +12,7 @@ import ( "encoding/base64" "encoding/binary" "encoding/pem" + "errors" "fmt" "io" "net" @@ -27,14 +28,80 @@ import ( // Note: see comment in handshake_test.go for details of how the reference // tests work. -// blockingSource is an io.Reader that blocks a Read call until it's closed. -type blockingSource chan bool +// opensslInputEvent enumerates possible inputs that can be sent to an `openssl +// s_client` process. +type opensslInputEvent int + +const ( + // opensslRenegotiate causes OpenSSL to request a renegotiation of the + // connection. + opensslRenegotiate opensslInputEvent = iota + + // opensslSendBanner causes OpenSSL to send the contents of + // opensslSentinel on the connection. + opensslSendSentinel +) + +const opensslSentinel = "SENTINEL\n" + +type opensslInput chan opensslInputEvent + +func (i opensslInput) Read(buf []byte) (n int, err error) { + for event := range i { + switch event { + case opensslRenegotiate: + return copy(buf, []byte("R\n")), nil + case opensslSendSentinel: + return copy(buf, []byte(opensslSentinel)), nil + default: + panic("unknown event") + } + } -func (b blockingSource) Read([]byte) (n int, err error) { - <-b return 0, io.EOF } +// opensslOutputSink is an io.Writer that receives the stdout and stderr from +// an `openssl` process and sends a value to handshakeComplete when it sees a +// log message from a completed server handshake. +type opensslOutputSink struct { + handshakeComplete chan struct{} + all []byte + line []byte +} + +func newOpensslOutputSink() *opensslOutputSink { + return &opensslOutputSink{make(chan struct{}), nil, nil} +} + +// opensslEndOfHandshake is a message that the “openssl s_server” tool will +// print when a handshake completes if run with “-state”. +const opensslEndOfHandshake = "SSL_accept:SSLv3 write finished A" + +func (o *opensslOutputSink) Write(data []byte) (n int, err error) { + o.line = append(o.line, data...) + o.all = append(o.all, data...) + + for { + i := bytes.Index(o.line, []byte{'\n'}) + if i < 0 { + break + } + + if bytes.Equal([]byte(opensslEndOfHandshake), o.line[:i]) { + o.handshakeComplete <- struct{}{} + } + o.line = o.line[i+1:] + } + + return len(data), nil +} + +func (o *opensslOutputSink) WriteTo(w io.Writer) (int64, error) { + n, err := w.Write(o.all) + return int64(n), err +} + // clientTest represents a test of the TLS client handshake against a reference // implementation. type clientTest struct { @@ -60,15 +127,25 @@ type clientTest struct { // ConnectionState of the resulting connection. It returns a non-nil // error if the ConnectionState is unacceptable. validate func(ConnectionState) error + // numRenegotiations is the number of times that the connection will be + // renegotiated. + numRenegotiations int + // renegotiationExpectedToFail, if not zero, is the number of the + // renegotiation attempt that is expected to fail. + renegotiationExpectedToFail int + // checkRenegotiationError, if not nil, is called with any error + // arising from renegotiation. It can map expected errors to nil to + // ignore them. + checkRenegotiationError func(renegotiationNum int, err error) error } var defaultServerCommand = []string{"openssl", "s_server"} // connFromCommand starts the reference server process, connects to it and -// returns a recordingConn for the connection. The stdin return value is a -// blockingSource for the stdin of the child process. It must be closed before +// returns a recordingConn for the connection. The stdin return value is an +// opensslInput for the stdin of the child process. It must be closed before // Waiting for child. -func (test *clientTest) connFromCommand() (conn *recordingConn, child *exec.Cmd, stdin blockingSource, err error) { +func (test *clientTest) connFromCommand() (conn *recordingConn, child *exec.Cmd, stdin opensslInput, stdout *opensslOutputSink, err error) { cert := testRSACertificate if len(test.cert) > 0 { cert = test.cert @@ -131,14 +208,28 @@ func (test *clientTest) connFromCommand() (conn *recordingConn, child *exec.Cmd, command = append(command, "-serverinfo", serverInfoPath) } + if test.numRenegotiations > 0 { + found := false + for _, flag := range command[1:] { + if flag == "-state" { + found = true + break + } + } + + if !found { + panic("-state flag missing to OpenSSL. You need this if testing renegotiation") + } + } + cmd := exec.Command(command[0], command[1:]...) - stdin = blockingSource(make(chan bool)) + stdin = opensslInput(make(chan opensslInputEvent)) cmd.Stdin = stdin - var out bytes.Buffer - cmd.Stdout = &out - cmd.Stderr = &out + out := newOpensslOutputSink() + cmd.Stdout = out + cmd.Stderr = out if err := cmd.Start(); err != nil { - return nil, nil, nil, err + return nil, nil, nil, nil, err } // OpenSSL does print an "ACCEPT" banner, but it does so *before* @@ -160,14 +251,14 @@ func (test *clientTest) connFromCommand() (conn *recordingConn, child *exec.Cmd, close(stdin) out.WriteTo(os.Stdout) cmd.Process.Kill() - return nil, nil, nil, cmd.Wait() + return nil, nil, nil, nil, cmd.Wait() } record := &recordingConn{ Conn: tcpConn, } - return record, cmd, stdin, nil + return record, cmd, stdin, out, nil } func (test *clientTest) dataPath() string { @@ -187,11 +278,12 @@ func (test *clientTest) run(t *testing.T, write bool) { var clientConn, serverConn net.Conn var recordingConn *recordingConn var childProcess *exec.Cmd - var stdin blockingSource + var stdin opensslInput + var stdout *opensslOutputSink if write { var err error - recordingConn, childProcess, stdin, err = test.connFromCommand() + recordingConn, childProcess, stdin, stdout, err = test.connFromCommand() if err != nil { t.Fatalf("Failed to start subcommand: %s", err) } @@ -208,17 +300,77 @@ func (test *clientTest) run(t *testing.T, write bool) { doneChan := make(chan bool) go func() { + defer func() { doneChan <- true }() + defer clientConn.Close() + defer client.Close() + if _, err := client.Write([]byte("hello\n")); err != nil { t.Errorf("Client.Write failed: %s", err) + return } + + for i := 1; i <= test.numRenegotiations; i++ { + // The initial handshake will generate a + // handshakeComplete signal which needs to be quashed. + if i == 1 && write { + <-stdout.handshakeComplete + } + + // OpenSSL will try to interleave application data and + // a renegotiation if we send both concurrently. + // Therefore: ask OpensSSL to start a renegotiation, run + // a goroutine to call client.Read and thus process the + // renegotiation request, watch for OpenSSL's stdout to + // indicate that the handshake is complete and, + // finally, have OpenSSL write something to cause + // client.Read to complete. + if write { + stdin <- opensslRenegotiate + } + + signalChan := make(chan struct{}) + + go func() { + defer func() { signalChan <- struct{}{} }() + + buf := make([]byte, 256) + n, err := client.Read(buf) + + if test.checkRenegotiationError != nil { + newErr := test.checkRenegotiationError(i, err) + if err != nil && newErr == nil { + return + } + err = newErr + } + + if err != nil { + t.Errorf("Client.Read failed after renegotiation #%d: %s", i, err) + return + } + + buf = buf[:n] + if !bytes.Equal([]byte(opensslSentinel), buf) { + t.Errorf("Client.Read returned %q, but wanted %q", string(buf), opensslSentinel) + } + + if expected := i + 1; client.handshakes != expected { + t.Errorf("client should have recorded %d handshakes, but believes that %d have occured", expected, client.handshakes) + } + }() + + if write && test.renegotiationExpectedToFail != i { + <-stdout.handshakeComplete + stdin <- opensslSendSentinel + } + <-signalChan + } + if test.validate != nil { if err := test.validate(client.ConnectionState()); err != nil { t.Errorf("validate callback returned error: %s", err) } } - client.Close() - clientConn.Close() - doneChan <- true }() if !write { @@ -357,14 +509,14 @@ func TestHandshakeClientAES256GCMSHA384(t *testing.T) { } func TestHandshakeClientCertRSA(t *testing.T) { - config := *testConfig + config := testConfig.clone() cert, _ := X509KeyPair([]byte(clientCertificatePEM), []byte(clientKeyPEM)) config.Certificates = []Certificate{cert} test := &clientTest{ name: "ClientCert-RSA-RSA", command: []string{"openssl", "s_server", "-cipher", "RC4-SHA", "-verify", "1"}, - config: &config, + config: config, } runClientTestTLS10(t, test) @@ -373,7 +525,7 @@ func TestHandshakeClientCertRSA(t *testing.T) { test = &clientTest{ name: "ClientCert-RSA-ECDSA", command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-SHA", "-verify", "1"}, - config: &config, + config: config, cert: testECDSACertificate, key: testECDSAPrivateKey, } @@ -384,7 +536,7 @@ func TestHandshakeClientCertRSA(t *testing.T) { test = &clientTest{ name: "ClientCert-RSA-AES256-GCM-SHA384", command: []string{"openssl", "s_server", "-cipher", "ECDHE-RSA-AES256-GCM-SHA384", "-verify", "1"}, - config: &config, + config: config, cert: testRSACertificate, key: testRSAPrivateKey, } @@ -393,14 +545,14 @@ func TestHandshakeClientCertRSA(t *testing.T) { } func TestHandshakeClientCertECDSA(t *testing.T) { - config := *testConfig + config := testConfig.clone() cert, _ := X509KeyPair([]byte(clientECDSACertificatePEM), []byte(clientECDSAKeyPEM)) config.Certificates = []Certificate{cert} test := &clientTest{ name: "ClientCert-ECDSA-RSA", command: []string{"openssl", "s_server", "-cipher", "RC4-SHA", "-verify", "1"}, - config: &config, + config: config, } runClientTestTLS10(t, test) @@ -409,7 +561,7 @@ func TestHandshakeClientCertECDSA(t *testing.T) { test = &clientTest{ name: "ClientCert-ECDSA-ECDSA", command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-SHA", "-verify", "1"}, - config: &config, + config: config, cert: testECDSACertificate, key: testECDSAPrivateKey, } @@ -448,7 +600,7 @@ func TestClientResumption(t *testing.T) { t.Fatalf("%s resumed: %v, expected: %v", test, hs.DidResume, didResume) } if didResume && (hs.PeerCertificates == nil || hs.VerifiedChains == nil) { - t.Fatalf("expected non-nil certificates after resumption. Got peerCertificates: %#v, verifedCertificates: %#v", hs.PeerCertificates, hs.VerifiedChains) + t.Fatalf("expected non-nil certificates after resumption. Got peerCertificates: %#v, verifiedCertificates: %#v", hs.PeerCertificates, hs.VerifiedChains) } } @@ -539,7 +691,7 @@ func TestLRUClientSessionCache(t *testing.T) { } func TestHandshakeClientALPNMatch(t *testing.T) { - config := *testConfig + config := testConfig.clone() config.NextProtos = []string{"proto2", "proto1"} test := &clientTest{ @@ -547,7 +699,7 @@ func TestHandshakeClientALPNMatch(t *testing.T) { // Note that this needs OpenSSL 1.0.2 because that is the first // version that supports the -alpn flag. command: []string{"openssl", "s_server", "-alpn", "proto1,proto2"}, - config: &config, + config: config, validate: func(state ConnectionState) error { // The server's preferences should override the client. if state.NegotiatedProtocol != "proto1" { @@ -560,7 +712,7 @@ func TestHandshakeClientALPNMatch(t *testing.T) { } func TestHandshakeClientALPNNoMatch(t *testing.T) { - config := *testConfig + config := testConfig.clone() config.NextProtos = []string{"proto3"} test := &clientTest{ @@ -568,7 +720,7 @@ func TestHandshakeClientALPNNoMatch(t *testing.T) { // Note that this needs OpenSSL 1.0.2 because that is the first // version that supports the -alpn flag. command: []string{"openssl", "s_server", "-alpn", "proto1,proto2"}, - config: &config, + config: config, validate: func(state ConnectionState) error { // There's no overlap so OpenSSL will not select a protocol. if state.NegotiatedProtocol != "" { @@ -584,7 +736,7 @@ func TestHandshakeClientALPNNoMatch(t *testing.T) { const sctsBase64 = "ABIBaQFnAHUApLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BAAAAFHl5nuFgAABAMARjBEAiAcS4JdlW5nW9sElUv2zvQyPoZ6ejKrGGB03gjaBZFMLwIgc1Qbbn+hsH0RvObzhS+XZhr3iuQQJY8S9G85D9KeGPAAdgBo9pj4H2SCvjqM7rkoHUz8cVFdZ5PURNEKZ6y7T0/7xAAAAUeX4bVwAAAEAwBHMEUCIDIhFDgG2HIuADBkGuLobU5a4dlCHoJLliWJ1SYT05z6AiEAjxIoZFFPRNWMGGIjskOTMwXzQ1Wh2e7NxXE1kd1J0QsAdgDuS723dc5guuFCaR+r4Z5mow9+X7By2IMAxHuJeqj9ywAAAUhcZIqHAAAEAwBHMEUCICmJ1rBT09LpkbzxtUC+Hi7nXLR0J+2PmwLp+sJMuqK+AiEAr0NkUnEVKVhAkccIFpYDqHOlZaBsuEhWWrYpg2RtKp0=" func TestHandshakClientSCTs(t *testing.T) { - config := *testConfig + config := testConfig.clone() scts, err := base64.StdEncoding.DecodeString(sctsBase64) if err != nil { @@ -596,7 +748,7 @@ func TestHandshakClientSCTs(t *testing.T) { // Note that this needs OpenSSL 1.0.2 because that is the first // version that supports the -serverinfo flag. command: []string{"openssl", "s_server"}, - config: &config, + config: config, extensions: [][]byte{scts}, validate: func(state ConnectionState) error { expectedSCTs := [][]byte{ @@ -618,14 +770,113 @@ func TestHandshakClientSCTs(t *testing.T) { runClientTestTLS12(t, test) } -func TestNoIPAddressesInSNI(t *testing.T) { - for _, ipLiteral := range []string{"1.2.3.4", "::1"} { +func TestRenegotiationRejected(t *testing.T) { + config := testConfig.clone() + test := &clientTest{ + name: "RenegotiationRejected", + command: []string{"openssl", "s_server", "-state"}, + config: config, + numRenegotiations: 1, + renegotiationExpectedToFail: 1, + checkRenegotiationError: func(renegotiationNum int, err error) error { + if err == nil { + return errors.New("expected error from renegotiation but got nil") + } + if !strings.Contains(err.Error(), "no renegotiation") { + return fmt.Errorf("expected renegotiation to be rejected but got %q", err) + } + return nil + }, + } + + runClientTestTLS12(t, test) +} + +func TestRenegotiateOnce(t *testing.T) { + config := testConfig.clone() + config.Renegotiation = RenegotiateOnceAsClient + + test := &clientTest{ + name: "RenegotiateOnce", + command: []string{"openssl", "s_server", "-state"}, + config: config, + numRenegotiations: 1, + } + + runClientTestTLS12(t, test) +} + +func TestRenegotiateTwice(t *testing.T) { + config := testConfig.clone() + config.Renegotiation = RenegotiateFreelyAsClient + + test := &clientTest{ + name: "RenegotiateTwice", + command: []string{"openssl", "s_server", "-state"}, + config: config, + numRenegotiations: 2, + } + + runClientTestTLS12(t, test) +} + +func TestRenegotiateTwiceRejected(t *testing.T) { + config := testConfig.clone() + config.Renegotiation = RenegotiateOnceAsClient + + test := &clientTest{ + name: "RenegotiateTwiceRejected", + command: []string{"openssl", "s_server", "-state"}, + config: config, + numRenegotiations: 2, + renegotiationExpectedToFail: 2, + checkRenegotiationError: func(renegotiationNum int, err error) error { + if renegotiationNum == 1 { + return err + } + + if err == nil { + return errors.New("expected error from renegotiation but got nil") + } + if !strings.Contains(err.Error(), "no renegotiation") { + return fmt.Errorf("expected renegotiation to be rejected but got %q", err) + } + return nil + }, + } + + runClientTestTLS12(t, test) +} + +var hostnameInSNITests = []struct { + in, out string +}{ + // Opaque string + {"", ""}, + {"localhost", "localhost"}, + {"foo, bar, baz and qux", "foo, bar, baz and qux"}, + + // DNS hostname + {"golang.org", "golang.org"}, + {"golang.org.", "golang.org"}, + + // Literal IPv4 address + {"1.2.3.4", ""}, + + // Literal IPv6 address + {"::1", ""}, + {"::1%lo0", ""}, // with zone identifier + {"[::1]", ""}, // as per RFC 5952 we allow the [] style as IPv6 literal + {"[::1%lo0]", ""}, +} + +func TestHostnameInSNI(t *testing.T) { + for _, tt := range hostnameInSNITests { c, s := net.Pipe() - go func() { - client := Client(c, &Config{ServerName: ipLiteral}) - client.Handshake() - }() + go func(host string) { + Client(c, &Config{ServerName: host, InsecureSkipVerify: true}).Handshake() + }(tt.in) var header [5]byte if _, err := io.ReadFull(s, header[:]); err != nil { @@ -637,10 +888,20 @@ func TestNoIPAddressesInSNI(t *testing.T) { if _, err := io.ReadFull(s, record[:]); err != nil { t.Fatal(err) } + + c.Close() s.Close() - if bytes.Index(record, []byte(ipLiteral)) != -1 { - t.Errorf("IP literal %q found in ClientHello: %x", ipLiteral, record) + var m clientHelloMsg + if !m.unmarshal(record) { + t.Errorf("unmarshaling ClientHello for %q failed", tt.in) + continue + } + if tt.in != tt.out && m.serverName == tt.in { + t.Errorf("prohibited %q found in ClientHello: %x", tt.in, record) + } + if m.serverName != tt.out { + t.Errorf("expected %q not found in ClientHello: %x", tt.out, record) } } } @@ -694,3 +955,93 @@ func TestServerSelectingUnconfiguredCipherSuite(t *testing.T) { t.Fatalf("Expected error about unconfigured cipher suite but got %q", err) } } + +// brokenConn wraps a net.Conn and causes all Writes after a certain number to +// fail with brokenConnErr. +type brokenConn struct { + net.Conn + + // breakAfter is the number of successful writes that will be allowed + // before all subsequent writes fail. + breakAfter int + + // numWrites is the number of writes that have been done. + numWrites int +} + +// brokenConnErr is the error that brokenConn returns once exhausted. +var brokenConnErr = errors.New("too many writes to brokenConn") + +func (b *brokenConn) Write(data []byte) (int, error) { + if b.numWrites >= b.breakAfter { + return 0, brokenConnErr + } + + b.numWrites++ + return b.Conn.Write(data) +} + +func TestFailedWrite(t *testing.T) { + // Test that a write error during the handshake is returned. + for _, breakAfter := range []int{0, 1} { + c, s := net.Pipe() + done := make(chan bool) + + go func() { + Server(s, testConfig).Handshake() + s.Close() + done <- true + }() + + brokenC := &brokenConn{Conn: c, breakAfter: breakAfter} + err := Client(brokenC, testConfig).Handshake() + if err != brokenConnErr { + t.Errorf("#%d: expected error from brokenConn but got %q", breakAfter, err) + } + brokenC.Close() + + <-done + } +} + +// writeCountingConn wraps a net.Conn and counts the number of Write calls. +type writeCountingConn struct { + net.Conn + + // numWrites is the number of writes that have been done. + numWrites int +} + +func (wcc *writeCountingConn) Write(data []byte) (int, error) { + wcc.numWrites++ + return wcc.Conn.Write(data) +} + +func TestBuffering(t *testing.T) { + c, s := net.Pipe() + done := make(chan bool) + + clientWCC := &writeCountingConn{Conn: c} + serverWCC := &writeCountingConn{Conn: s} + + go func() { + Server(serverWCC, testConfig).Handshake() + serverWCC.Close() + done <- true + }() + + err := Client(clientWCC, testConfig).Handshake() + if err != nil { + t.Fatal(err) + } + clientWCC.Close() + <-done + + if n := clientWCC.numWrites; n != 2 { + t.Errorf("expected client handshake to complete with only two writes, but saw %d", n) + } + + if n := serverWCC.numWrites; n != 2 { + t.Errorf("expected server handshake to complete with only two writes, but saw %d", n) + } +} diff --git a/libgo/go/crypto/tls/handshake_messages.go b/libgo/go/crypto/tls/handshake_messages.go index 111ce53..ab8e60a 100644 --- a/libgo/go/crypto/tls/handshake_messages.go +++ b/libgo/go/crypto/tls/handshake_messages.go @@ -7,23 +7,24 @@ package tls import "bytes" type clientHelloMsg struct { - raw []byte - vers uint16 - random []byte - sessionId []byte - cipherSuites []uint16 - compressionMethods []uint8 - nextProtoNeg bool - serverName string - ocspStapling bool - scts bool - supportedCurves []CurveID - supportedPoints []uint8 - ticketSupported bool - sessionTicket []uint8 - signatureAndHashes []signatureAndHash - secureRenegotiation bool - alpnProtocols []string + raw []byte + vers uint16 + random []byte + sessionId []byte + cipherSuites []uint16 + compressionMethods []uint8 + nextProtoNeg bool + serverName string + ocspStapling bool + scts bool + supportedCurves []CurveID + supportedPoints []uint8 + ticketSupported bool + sessionTicket []uint8 + signatureAndHashes []signatureAndHash + secureRenegotiation []byte + secureRenegotiationSupported bool + alpnProtocols []string } func (m *clientHelloMsg) equal(i interface{}) bool { @@ -47,7 +48,8 @@ func (m *clientHelloMsg) equal(i interface{}) bool { m.ticketSupported == m1.ticketSupported && bytes.Equal(m.sessionTicket, m1.sessionTicket) && eqSignatureAndHashes(m.signatureAndHashes, m1.signatureAndHashes) && - m.secureRenegotiation == m1.secureRenegotiation && + m.secureRenegotiationSupported == m1.secureRenegotiationSupported && + bytes.Equal(m.secureRenegotiation, m1.secureRenegotiation) && eqStrings(m.alpnProtocols, m1.alpnProtocols) } @@ -86,8 +88,8 @@ func (m *clientHelloMsg) marshal() []byte { extensionsLength += 2 + 2*len(m.signatureAndHashes) numExtensions++ } - if m.secureRenegotiation { - extensionsLength += 1 + if m.secureRenegotiationSupported { + extensionsLength += 1 + len(m.secureRenegotiation) numExtensions++ } if len(m.alpnProtocols) > 0 { @@ -214,7 +216,7 @@ func (m *clientHelloMsg) marshal() []byte { z[4] = byte(l) z = z[5:] for _, pointFormat := range m.supportedPoints { - z[0] = byte(pointFormat) + z[0] = pointFormat z = z[1:] } } @@ -248,12 +250,15 @@ func (m *clientHelloMsg) marshal() []byte { z = z[2:] } } - if m.secureRenegotiation { + if m.secureRenegotiationSupported { z[0] = byte(extensionRenegotiationInfo >> 8) z[1] = byte(extensionRenegotiationInfo & 0xff) z[2] = 0 - z[3] = 1 + z[3] = byte(len(m.secureRenegotiation) + 1) + z[4] = byte(len(m.secureRenegotiation)) z = z[5:] + copy(z, m.secureRenegotiation) + z = z[len(m.secureRenegotiation):] } if len(m.alpnProtocols) > 0 { z[0] = byte(extensionALPN >> 8) @@ -316,7 +321,7 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool { for i := 0; i < numCipherSuites; i++ { m.cipherSuites[i] = uint16(data[2+2*i])<<8 | uint16(data[3+2*i]) if m.cipherSuites[i] == scsvRenegotiation { - m.secureRenegotiation = true + m.secureRenegotiationSupported = true } } data = data[2+cipherSuiteLen:] @@ -448,10 +453,18 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool { d = d[2:] } case extensionRenegotiationInfo: - if length != 1 || data[0] != 0 { + if length == 0 { + return false + } + d := data[:length] + l := int(d[0]) + d = d[1:] + if l != len(d) { return false } - m.secureRenegotiation = true + + m.secureRenegotiation = d + m.secureRenegotiationSupported = true case extensionALPN: if length < 2 { return false @@ -483,19 +496,20 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool { } type serverHelloMsg struct { - raw []byte - vers uint16 - random []byte - sessionId []byte - cipherSuite uint16 - compressionMethod uint8 - nextProtoNeg bool - nextProtos []string - ocspStapling bool - scts [][]byte - ticketSupported bool - secureRenegotiation bool - alpnProtocol string + raw []byte + vers uint16 + random []byte + sessionId []byte + cipherSuite uint16 + compressionMethod uint8 + nextProtoNeg bool + nextProtos []string + ocspStapling bool + scts [][]byte + ticketSupported bool + secureRenegotiation []byte + secureRenegotiationSupported bool + alpnProtocol string } func (m *serverHelloMsg) equal(i interface{}) bool { @@ -523,7 +537,8 @@ func (m *serverHelloMsg) equal(i interface{}) bool { eqStrings(m.nextProtos, m1.nextProtos) && m.ocspStapling == m1.ocspStapling && m.ticketSupported == m1.ticketSupported && - m.secureRenegotiation == m1.secureRenegotiation && + m.secureRenegotiationSupported == m1.secureRenegotiationSupported && + bytes.Equal(m.secureRenegotiation, m1.secureRenegotiation) && m.alpnProtocol == m1.alpnProtocol } @@ -551,8 +566,8 @@ func (m *serverHelloMsg) marshal() []byte { if m.ticketSupported { numExtensions++ } - if m.secureRenegotiation { - extensionsLength += 1 + if m.secureRenegotiationSupported { + extensionsLength += 1 + len(m.secureRenegotiation) numExtensions++ } if alpnLen := len(m.alpnProtocol); alpnLen > 0 { @@ -589,7 +604,7 @@ func (m *serverHelloMsg) marshal() []byte { z := x[39+len(m.sessionId):] z[0] = uint8(m.cipherSuite >> 8) z[1] = uint8(m.cipherSuite) - z[2] = uint8(m.compressionMethod) + z[2] = m.compressionMethod z = z[3:] if numExtensions > 0 { @@ -624,12 +639,15 @@ func (m *serverHelloMsg) marshal() []byte { z[1] = byte(extensionSessionTicket) z = z[4:] } - if m.secureRenegotiation { + if m.secureRenegotiationSupported { z[0] = byte(extensionRenegotiationInfo >> 8) z[1] = byte(extensionRenegotiationInfo & 0xff) z[2] = 0 - z[3] = 1 + z[3] = byte(len(m.secureRenegotiation) + 1) + z[4] = byte(len(m.secureRenegotiation)) z = z[5:] + copy(z, m.secureRenegotiation) + z = z[len(m.secureRenegotiation):] } if alpnLen := len(m.alpnProtocol); alpnLen > 0 { z[0] = byte(extensionALPN >> 8) @@ -744,10 +762,18 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool { } m.ticketSupported = true case extensionRenegotiationInfo: - if length != 1 || data[0] != 0 { + if length == 0 { + return false + } + d := data[:length] + l := int(d[0]) + d = d[1:] + if l != len(d) { return false } - m.secureRenegotiation = true + + m.secureRenegotiation = d + m.secureRenegotiationSupported = true case extensionALPN: d := data[:length] if len(d) < 3 { @@ -1316,11 +1342,8 @@ func (m *certificateRequestMsg) unmarshal(data []byte) bool { m.certificateAuthorities = append(m.certificateAuthorities, cas[:caLen]) cas = cas[caLen:] } - if len(data) > 0 { - return false - } - return true + return len(data) == 0 } type certificateVerifyMsg struct { @@ -1466,6 +1489,17 @@ func (m *newSessionTicketMsg) unmarshal(data []byte) bool { return true } +type helloRequestMsg struct { +} + +func (*helloRequestMsg) marshal() []byte { + return []byte{typeHelloRequest, 0, 0, 0} +} + +func (*helloRequestMsg) unmarshal(data []byte) bool { + return len(data) == 4 +} + func eqUint16s(x, y []uint16) bool { if len(x) != len(y) { return false diff --git a/libgo/go/crypto/tls/handshake_server.go b/libgo/go/crypto/tls/handshake_server.go index e16cddcb..1aac729 100644 --- a/libgo/go/crypto/tls/handshake_server.go +++ b/libgo/go/crypto/tls/handshake_server.go @@ -35,6 +35,7 @@ type serverHandshakeState struct { } // serverHandshake performs a TLS handshake as a server. +// c.out.Mutex <= L; c.handshakeMutex <= L. func (c *Conn) serverHandshake() error { config := c.config @@ -51,6 +52,7 @@ func (c *Conn) serverHandshake() error { } // For an overview of TLS handshaking, see https://tools.ietf.org/html/rfc5246#section-7.3 + c.buffering = true if isResume { // The client has included a session ticket and so we do an abbreviated handshake. if err := hs.doResumeHandshake(); err != nil { @@ -67,9 +69,13 @@ func (c *Conn) serverHandshake() error { return err } } - if err := hs.sendFinished(c.firstFinished[:]); err != nil { + if err := hs.sendFinished(c.serverFinished[:]); err != nil { return err } + if _, err := c.flush(); err != nil { + return err + } + c.clientFinishedIsFirst = false if err := hs.readFinished(nil); err != nil { return err } @@ -83,15 +89,20 @@ func (c *Conn) serverHandshake() error { if err := hs.establishKeys(); err != nil { return err } - if err := hs.readFinished(c.firstFinished[:]); err != nil { + if err := hs.readFinished(c.clientFinished[:]); err != nil { return err } + c.clientFinishedIsFirst = true + c.buffering = true if err := hs.sendSessionTicket(); err != nil { return err } if err := hs.sendFinished(nil); err != nil { return err } + if _, err := c.flush(); err != nil { + return err + } } c.handshakeComplete = true @@ -165,7 +176,13 @@ Curves: c.sendAlert(alertInternalError) return false, err } - hs.hello.secureRenegotiation = hs.clientHello.secureRenegotiation + + if len(hs.clientHello.secureRenegotiation) != 0 { + c.sendAlert(alertHandshakeFailure) + return false, errors.New("tls: initial handshake had non-empty renegotiation extension") + } + + hs.hello.secureRenegotiationSupported = hs.clientHello.secureRenegotiationSupported hs.hello.compressionMethod = compressionNone if len(hs.clientHello.serverName) > 0 { c.serverName = hs.clientHello.serverName @@ -187,12 +204,13 @@ Curves: } } - if hs.cert, err = config.getCertificate(&ClientHelloInfo{ + hs.cert, err = config.getCertificate(&ClientHelloInfo{ CipherSuites: hs.clientHello.cipherSuites, ServerName: hs.clientHello.serverName, SupportedCurves: hs.clientHello.supportedCurves, SupportedPoints: hs.clientHello.supportedPoints, - }); err != nil { + }) + if err != nil { c.sendAlert(alertInternalError) return false, err } @@ -208,7 +226,7 @@ Curves: hs.rsaSignOk = true default: c.sendAlert(alertInternalError) - return false, fmt.Errorf("crypto/tls: unsupported signing key type (%T)", priv.Public()) + return false, fmt.Errorf("tls: unsupported signing key type (%T)", priv.Public()) } } if priv, ok := hs.cert.PrivateKey.(crypto.Decrypter); ok { @@ -217,7 +235,7 @@ Curves: hs.rsaDecryptOk = true default: c.sendAlert(alertInternalError) - return false, fmt.Errorf("crypto/tls: unsupported decryption key type (%T)", priv.Public()) + return false, fmt.Errorf("tls: unsupported decryption key type (%T)", priv.Public()) } } @@ -245,7 +263,7 @@ Curves: 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. + // See https://tools.ietf.org/html/rfc7507. for _, id := range hs.clientHello.cipherSuites { if id == TLS_FALLBACK_SCSV { // The client is doing a fallback connection. @@ -274,10 +292,8 @@ func (hs *serverHandshakeState) checkForResumption() bool { 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 { + // Never resume a session for a different TLS version. + if c.vers != hs.sessionState.vers { return false } @@ -322,7 +338,9 @@ func (hs *serverHandshakeState) doResumeHandshake() error { hs.finishedHash.discardHandshakeBuffer() hs.finishedHash.Write(hs.clientHello.marshal()) hs.finishedHash.Write(hs.hello.marshal()) - c.writeRecord(recordTypeHandshake, hs.hello.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, hs.hello.marshal()); err != nil { + return err + } if len(hs.sessionState.certificates) > 0 { if _, err := hs.processCertsFromClient(hs.sessionState.certificates); err != nil { @@ -354,19 +372,25 @@ func (hs *serverHandshakeState) doFullHandshake() error { } hs.finishedHash.Write(hs.clientHello.marshal()) hs.finishedHash.Write(hs.hello.marshal()) - c.writeRecord(recordTypeHandshake, hs.hello.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, hs.hello.marshal()); err != nil { + return err + } certMsg := new(certificateMsg) certMsg.certificates = hs.cert.Certificate hs.finishedHash.Write(certMsg.marshal()) - c.writeRecord(recordTypeHandshake, certMsg.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil { + return err + } 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()) + if _, err := c.writeRecord(recordTypeHandshake, certStatus.marshal()); err != nil { + return err + } } keyAgreement := hs.suite.ka(c.vers) @@ -377,7 +401,9 @@ func (hs *serverHandshakeState) doFullHandshake() error { } if skx != nil { hs.finishedHash.Write(skx.marshal()) - c.writeRecord(recordTypeHandshake, skx.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, skx.marshal()); err != nil { + return err + } } if config.ClientAuth >= RequestClientCert { @@ -401,12 +427,20 @@ func (hs *serverHandshakeState) doFullHandshake() error { certReq.certificateAuthorities = config.ClientCAs.Subjects() } hs.finishedHash.Write(certReq.marshal()) - c.writeRecord(recordTypeHandshake, certReq.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, certReq.marshal()); err != nil { + return err + } } helloDone := new(serverHelloDoneMsg) hs.finishedHash.Write(helloDone.marshal()) - c.writeRecord(recordTypeHandshake, helloDone.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, helloDone.marshal()); err != nil { + return err + } + + if _, err := c.flush(); err != nil { + return err + } var pub crypto.PublicKey // public key for client auth, if any @@ -462,7 +496,7 @@ func (hs *serverHandshakeState) doFullHandshake() error { // 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 + // 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. @@ -499,7 +533,7 @@ func (hs *serverHandshakeState) doFullHandshake() error { switch key := pub.(type) { case *ecdsa.PublicKey: if signatureAndHash.signature != signatureECDSA { - err = errors.New("bad signature type for client's ECDSA certificate") + err = errors.New("tls: bad signature type for client's ECDSA certificate") break } ecdsaSig := new(ecdsaSignature) @@ -507,7 +541,7 @@ func (hs *serverHandshakeState) doFullHandshake() error { break } if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 { - err = errors.New("ECDSA signature contained zero or negative values") + err = errors.New("tls: ECDSA signature contained zero or negative values") break } var digest []byte @@ -515,11 +549,11 @@ func (hs *serverHandshakeState) doFullHandshake() error { break } if !ecdsa.Verify(key, digest, ecdsaSig.R, ecdsaSig.S) { - err = errors.New("ECDSA verification failure") + err = errors.New("tls: ECDSA verification failure") } case *rsa.PublicKey: if signatureAndHash.signature != signatureRSA { - err = errors.New("bad signature type for client's RSA certificate") + err = errors.New("tls: bad signature type for client's RSA certificate") break } var digest []byte @@ -571,8 +605,8 @@ func (hs *serverHandshakeState) readFinished(out []byte) error { c := hs.c c.readRecord(recordTypeChangeCipherSpec) - if err := c.in.error(); err != nil { - return err + if c.in.err != nil { + return c.in.err } if hs.hello.nextProtoNeg { @@ -632,7 +666,9 @@ func (hs *serverHandshakeState) sendSessionTicket() error { } hs.finishedHash.Write(m.marshal()) - c.writeRecord(recordTypeHandshake, m.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, m.marshal()); err != nil { + return err + } return nil } @@ -640,12 +676,16 @@ func (hs *serverHandshakeState) sendSessionTicket() error { func (hs *serverHandshakeState) sendFinished(out []byte) error { c := hs.c - c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) + if _, err := c.writeRecord(recordTypeChangeCipherSpec, []byte{1}); err != nil { + return err + } finished := new(finishedMsg) finished.verifyData = hs.finishedHash.serverSum(hs.masterSecret) hs.finishedHash.Write(finished.marshal()) - c.writeRecord(recordTypeHandshake, finished.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, finished.marshal()); err != nil { + return err + } c.cipherSuite = hs.suite.id copy(out, finished.verifyData) @@ -690,20 +730,20 @@ func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (c 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 + if len(certs) == 0 { + return nil, nil } - return nil, nil + 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 } // setCipherSuite sets a cipherSuite with the given id as the serverHandshakeState diff --git a/libgo/go/crypto/tls/handshake_server_test.go b/libgo/go/crypto/tls/handshake_server_test.go index 438fb314..9ae5d11fc 100644 --- a/libgo/go/crypto/tls/handshake_server_test.go +++ b/libgo/go/crypto/tls/handshake_server_test.go @@ -69,7 +69,7 @@ func testClientHello(t *testing.T, serverConfig *Config, m handshakeMessage) { func testClientHelloFailure(t *testing.T, serverConfig *Config, m handshakeMessage, expectedSubStr string) { // Create in-memory network connection, - // send message to server. Should return + // send message to server. Should return // expected error. c, s := net.Pipe() go func() { @@ -80,7 +80,10 @@ func testClientHelloFailure(t *testing.T, serverConfig *Config, m handshakeMessa cli.writeRecord(recordTypeHandshake, m.marshal()) c.Close() }() - err := Server(s, serverConfig).Handshake() + hs := serverHandshakeState{ + c: Server(s, serverConfig), + } + _, err := hs.readClientHello() s.Close() if len(expectedSubStr) == 0 { if err != nil && err != io.EOF { @@ -105,16 +108,16 @@ func TestRejectBadProtocolVersion(t *testing.T) { func TestNoSuiteOverlap(t *testing.T) { clientHello := &clientHelloMsg{ - vers: 0x0301, + vers: VersionTLS10, cipherSuites: []uint16{0xff00}, - compressionMethods: []uint8{0}, + compressionMethods: []uint8{compressionNone}, } testClientHelloFailure(t, testConfig, clientHello, "no cipher suite supported by both client and server") } func TestNoCompressionOverlap(t *testing.T) { clientHello := &clientHelloMsg{ - vers: 0x0301, + vers: VersionTLS10, cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, compressionMethods: []uint8{0xff}, } @@ -123,56 +126,56 @@ func TestNoCompressionOverlap(t *testing.T) { func TestNoRC4ByDefault(t *testing.T) { clientHello := &clientHelloMsg{ - vers: 0x0301, + vers: VersionTLS10, cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, - compressionMethods: []uint8{0}, + compressionMethods: []uint8{compressionNone}, } - serverConfig := *testConfig + serverConfig := testConfig.clone() // Reset the enabled cipher suites to nil in order to test the // defaults. serverConfig.CipherSuites = nil - testClientHelloFailure(t, &serverConfig, clientHello, "no cipher suite supported by both client and server") + testClientHelloFailure(t, serverConfig, clientHello, "no cipher suite supported by both client and server") } func TestDontSelectECDSAWithRSAKey(t *testing.T) { // Test that, even when both sides support an ECDSA cipher suite, it // won't be selected if the server's private key doesn't support it. clientHello := &clientHelloMsg{ - vers: 0x0301, + vers: VersionTLS10, cipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA}, - compressionMethods: []uint8{0}, + compressionMethods: []uint8{compressionNone}, supportedCurves: []CurveID{CurveP256}, supportedPoints: []uint8{pointFormatUncompressed}, } - serverConfig := *testConfig + serverConfig := testConfig.clone() serverConfig.CipherSuites = clientHello.cipherSuites serverConfig.Certificates = make([]Certificate, 1) serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate} serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey serverConfig.BuildNameToCertificate() // First test that it *does* work when the server's key is ECDSA. - testClientHello(t, &serverConfig, clientHello) + testClientHello(t, serverConfig, clientHello) // Now test that switching to an RSA key causes the expected error (and // not an internal error about a signing failure). serverConfig.Certificates = testConfig.Certificates - testClientHelloFailure(t, &serverConfig, clientHello, "no cipher suite supported by both client and server") + testClientHelloFailure(t, serverConfig, clientHello, "no cipher suite supported by both client and server") } func TestDontSelectRSAWithECDSAKey(t *testing.T) { // Test that, even when both sides support an RSA cipher suite, it // won't be selected if the server's private key doesn't support it. clientHello := &clientHelloMsg{ - vers: 0x0301, + vers: VersionTLS10, cipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, - compressionMethods: []uint8{0}, + compressionMethods: []uint8{compressionNone}, supportedCurves: []CurveID{CurveP256}, supportedPoints: []uint8{pointFormatUncompressed}, } - serverConfig := *testConfig + serverConfig := testConfig.clone() serverConfig.CipherSuites = clientHello.cipherSuites // First test that it *does* work when the server's key is RSA. - testClientHello(t, &serverConfig, clientHello) + testClientHello(t, serverConfig, clientHello) // Now test that switching to an ECDSA key causes the expected error // (and not an internal error about a signing failure). @@ -180,16 +183,16 @@ func TestDontSelectRSAWithECDSAKey(t *testing.T) { serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate} serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey serverConfig.BuildNameToCertificate() - testClientHelloFailure(t, &serverConfig, clientHello, "no cipher suite supported by both client and server") + testClientHelloFailure(t, serverConfig, clientHello, "no cipher suite supported by both client and server") } func TestRenegotiationExtension(t *testing.T) { clientHello := &clientHelloMsg{ - vers: VersionTLS12, - compressionMethods: []uint8{compressionNone}, - random: make([]byte, 32), - secureRenegotiation: true, - cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, + vers: VersionTLS12, + compressionMethods: []uint8{compressionNone}, + random: make([]byte, 32), + secureRenegotiationSupported: true, + cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, } var buf []byte @@ -226,7 +229,7 @@ func TestRenegotiationExtension(t *testing.T) { t.Fatalf("Failed to parse ServerHello") } - if !serverHello.secureRenegotiation { + if !serverHello.secureRenegotiationSupported { t.Errorf("Secure renegotiation extension was not echoed.") } } @@ -262,9 +265,9 @@ func TestTLS12OnlyCipherSuites(t *testing.T) { reply, clientErr = cli.readHandshake() c.Close() }() - config := *testConfig + config := testConfig.clone() config.CipherSuites = clientHello.cipherSuites - Server(s, &config).Handshake() + Server(s, config).Handshake() s.Close() if clientErr != nil { t.Fatal(clientErr) @@ -396,6 +399,64 @@ func TestSCTHandshake(t *testing.T) { } } +func TestCrossVersionResume(t *testing.T) { + serverConfig := &Config{ + CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}, + Certificates: testConfig.Certificates, + } + clientConfig := &Config{ + CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}, + InsecureSkipVerify: true, + ClientSessionCache: NewLRUClientSessionCache(1), + ServerName: "servername", + } + + // Establish a session at TLS 1.1. + clientConfig.MaxVersion = VersionTLS11 + _, _, err := testHandshake(clientConfig, serverConfig) + if err != nil { + t.Fatalf("handshake failed: %s", err) + } + + // The client session cache now contains a TLS 1.1 session. + state, _, err := testHandshake(clientConfig, serverConfig) + if err != nil { + t.Fatalf("handshake failed: %s", err) + } + if !state.DidResume { + t.Fatalf("handshake did not resume at the same version") + } + + // Test that the server will decline to resume at a lower version. + clientConfig.MaxVersion = VersionTLS10 + state, _, err = testHandshake(clientConfig, serverConfig) + if err != nil { + t.Fatalf("handshake failed: %s", err) + } + if state.DidResume { + t.Fatalf("handshake resumed at a lower version") + } + + // The client session cache now contains a TLS 1.0 session. + state, _, err = testHandshake(clientConfig, serverConfig) + if err != nil { + t.Fatalf("handshake failed: %s", err) + } + if !state.DidResume { + t.Fatalf("handshake did not resume at the same version") + } + + // Test that the server will decline to resume at a higher version. + clientConfig.MaxVersion = VersionTLS11 + state, _, err = testHandshake(clientConfig, serverConfig) + if err != nil { + t.Fatalf("handshake failed: %s", err) + } + if state.DidResume { + t.Fatalf("handshake resumed at a higher version") + } +} + // Note: see comment in handshake_test.go for details of how the reference // tests work. @@ -518,16 +579,17 @@ func (test *serverTest) run(t *testing.T, write bool) { server := Server(serverConn, config) connStateChan := make(chan ConnectionState, 1) go func() { - var err error - if _, err = server.Write([]byte("hello, world\n")); err != nil { - t.Logf("Error from Server.Write: %s", err) - } + _, err := server.Write([]byte("hello, world\n")) if len(test.expectHandshakeErrorIncluding) > 0 { if err == nil { t.Errorf("Error expected, but no error returned") } else if s := err.Error(); !strings.Contains(s, test.expectHandshakeErrorIncluding) { t.Errorf("Error expected containing '%s' but got '%s'", test.expectHandshakeErrorIncluding, s) } + } else { + if err != nil { + t.Logf("Error from Server.Write: '%s'", err) + } } server.Close() serverConn.Close() @@ -670,7 +732,7 @@ func TestHandshakeServerAES256GCMSHA384(t *testing.T) { } func TestHandshakeServerECDHEECDSAAES(t *testing.T) { - config := *testConfig + config := testConfig.clone() config.Certificates = make([]Certificate, 1) config.Certificates[0].Certificate = [][]byte{testECDSACertificate} config.Certificates[0].PrivateKey = testECDSAPrivateKey @@ -679,14 +741,14 @@ func TestHandshakeServerECDHEECDSAAES(t *testing.T) { test := &serverTest{ name: "ECDHE-ECDSA-AES", command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "ECDHE-ECDSA-AES256-SHA"}, - config: &config, + config: config, } runServerTestTLS10(t, test) runServerTestTLS12(t, test) } func TestHandshakeServerALPN(t *testing.T) { - config := *testConfig + config := testConfig.clone() config.NextProtos = []string{"proto1", "proto2"} test := &serverTest{ @@ -694,7 +756,7 @@ func TestHandshakeServerALPN(t *testing.T) { // Note that this needs OpenSSL 1.0.2 because that is the first // version that supports the -alpn flag. command: []string{"openssl", "s_client", "-alpn", "proto2,proto1"}, - config: &config, + config: config, validate: func(state ConnectionState) error { // The server's preferences should override the client. if state.NegotiatedProtocol != "proto1" { @@ -707,7 +769,7 @@ func TestHandshakeServerALPN(t *testing.T) { } func TestHandshakeServerALPNNoMatch(t *testing.T) { - config := *testConfig + config := testConfig.clone() config.NextProtos = []string{"proto3"} test := &serverTest{ @@ -715,7 +777,7 @@ func TestHandshakeServerALPNNoMatch(t *testing.T) { // Note that this needs OpenSSL 1.0.2 because that is the first // version that supports the -alpn flag. command: []string{"openssl", "s_client", "-alpn", "proto2,proto1"}, - config: &config, + config: config, validate: func(state ConnectionState) error { // Rather than reject the connection, Go doesn't select // a protocol when there is no overlap. @@ -742,7 +804,7 @@ func TestHandshakeServerSNI(t *testing.T) { // TestHandshakeServerSNICertForName is similar to TestHandshakeServerSNI, but // tests the dynamic GetCertificate method func TestHandshakeServerSNIGetCertificate(t *testing.T) { - config := *testConfig + config := testConfig.clone() // Replace the NameToCertificate map with a GetCertificate function nameToCert := config.NameToCertificate @@ -754,7 +816,7 @@ func TestHandshakeServerSNIGetCertificate(t *testing.T) { test := &serverTest{ name: "SNI-GetCertificate", command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-servername", "snitest.com"}, - config: &config, + config: config, } runServerTestTLS12(t, test) } @@ -764,7 +826,7 @@ func TestHandshakeServerSNIGetCertificate(t *testing.T) { // GetCertificate method doesn't return a cert, we fall back to what's in // the NameToCertificate map. func TestHandshakeServerSNIGetCertificateNotFound(t *testing.T) { - config := *testConfig + config := testConfig.clone() config.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) { return nil, nil @@ -772,7 +834,7 @@ func TestHandshakeServerSNIGetCertificateNotFound(t *testing.T) { test := &serverTest{ name: "SNI-GetCertificateNotFound", command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-servername", "snitest.com"}, - config: &config, + config: config, } runServerTestTLS12(t, test) } @@ -782,18 +844,18 @@ func TestHandshakeServerSNIGetCertificateNotFound(t *testing.T) { func TestHandshakeServerSNIGetCertificateError(t *testing.T) { const errMsg = "TestHandshakeServerSNIGetCertificateError error" - serverConfig := *testConfig + serverConfig := testConfig.clone() serverConfig.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) { return nil, errors.New(errMsg) } clientHello := &clientHelloMsg{ - vers: 0x0301, + vers: VersionTLS10, cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, - compressionMethods: []uint8{0}, + compressionMethods: []uint8{compressionNone}, serverName: "test", } - testClientHelloFailure(t, &serverConfig, clientHello, errMsg) + testClientHelloFailure(t, serverConfig, clientHello, errMsg) } // TestHandshakeServerEmptyCertificates tests that GetCertificates is called in @@ -801,45 +863,45 @@ func TestHandshakeServerSNIGetCertificateError(t *testing.T) { func TestHandshakeServerEmptyCertificates(t *testing.T) { const errMsg = "TestHandshakeServerEmptyCertificates error" - serverConfig := *testConfig + serverConfig := testConfig.clone() serverConfig.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) { return nil, errors.New(errMsg) } serverConfig.Certificates = nil clientHello := &clientHelloMsg{ - vers: 0x0301, + vers: VersionTLS10, cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, - compressionMethods: []uint8{0}, + compressionMethods: []uint8{compressionNone}, } - testClientHelloFailure(t, &serverConfig, clientHello, errMsg) + testClientHelloFailure(t, serverConfig, clientHello, errMsg) // With an empty Certificates and a nil GetCertificate, the server // should always return a “no certificates” error. serverConfig.GetCertificate = nil clientHello = &clientHelloMsg{ - vers: 0x0301, + vers: VersionTLS10, cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, - compressionMethods: []uint8{0}, + compressionMethods: []uint8{compressionNone}, } - testClientHelloFailure(t, &serverConfig, clientHello, "no certificates") + testClientHelloFailure(t, serverConfig, clientHello, "no certificates") } // TestCipherSuiteCertPreferance ensures that we select an RSA ciphersuite with // an RSA certificate and an ECDSA ciphersuite with an ECDSA certificate. func TestCipherSuiteCertPreferenceECDSA(t *testing.T) { - config := *testConfig + config := testConfig.clone() config.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA} config.PreferServerCipherSuites = true test := &serverTest{ name: "CipherSuiteCertPreferenceRSA", - config: &config, + config: config, } runServerTestTLS12(t, test) - config = *testConfig + config = testConfig.clone() config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA} config.Certificates = []Certificate{ { @@ -852,7 +914,7 @@ func TestCipherSuiteCertPreferenceECDSA(t *testing.T) { test = &serverTest{ name: "CipherSuiteCertPreferenceECDSA", - config: &config, + config: config, } runServerTestTLS12(t, test) } @@ -878,12 +940,12 @@ func TestResumptionDisabled(t *testing.T) { sessionFilePath := tempFile("") defer os.Remove(sessionFilePath) - config := *testConfig + config := testConfig.clone() test := &serverTest{ name: "IssueTicketPreDisable", command: []string{"openssl", "s_client", "-cipher", "RC4-SHA", "-sess_out", sessionFilePath}, - config: &config, + config: config, } runServerTestTLS12(t, test) @@ -892,7 +954,7 @@ func TestResumptionDisabled(t *testing.T) { test = &serverTest{ name: "ResumeDisabled", command: []string{"openssl", "s_client", "-cipher", "RC4-SHA", "-sess_in", sessionFilePath}, - config: &config, + config: config, } runServerTestTLS12(t, test) @@ -901,12 +963,12 @@ func TestResumptionDisabled(t *testing.T) { } func TestFallbackSCSV(t *testing.T) { - serverConfig := &Config{ + serverConfig := Config{ Certificates: testConfig.Certificates, } test := &serverTest{ name: "FallbackSCSV", - config: serverConfig, + config: &serverConfig, // OpenSSL 1.0.1j is needed for the -fallback_scsv option. command: []string{"openssl", "s_client", "-fallback_scsv"}, expectHandshakeErrorIncluding: "inappropriate protocol fallback", @@ -991,20 +1053,20 @@ func TestClientAuth(t *testing.T) { defer os.Remove(ecdsaKeyPath) } - config := *testConfig + config := testConfig.clone() config.ClientAuth = RequestClientCert test := &serverTest{ name: "ClientAuthRequestedNotGiven", command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "RC4-SHA"}, - config: &config, + config: config, } runServerTestTLS12(t, test) test = &serverTest{ name: "ClientAuthRequestedAndGiven", command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "RC4-SHA", "-cert", certPath, "-key", keyPath}, - config: &config, + config: config, expectedPeerCerts: []string{clientCertificatePEM}, } runServerTestTLS12(t, test) @@ -1012,7 +1074,7 @@ func TestClientAuth(t *testing.T) { test = &serverTest{ name: "ClientAuthRequestedAndECDSAGiven", command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "RC4-SHA", "-cert", ecdsaCertPath, "-key", ecdsaKeyPath}, - config: &config, + config: config, expectedPeerCerts: []string{clientECDSACertificatePEM}, } runServerTestTLS12(t, test) diff --git a/libgo/go/crypto/tls/key_agreement.go b/libgo/go/crypto/tls/key_agreement.go index 0e6a7c2..467efb2 100644 --- a/libgo/go/crypto/tls/key_agreement.go +++ b/libgo/go/crypto/tls/key_agreement.go @@ -51,7 +51,7 @@ func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certifi if err != nil { return nil, err } - // We don't check the version number in the premaster secret. For one, + // 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 @@ -242,19 +242,19 @@ NextCandidate: case signatureECDSA: _, ok := priv.Public().(*ecdsa.PublicKey) if !ok { - return nil, errors.New("ECDHE ECDSA requires an ECDSA server key") + return nil, errors.New("tls: 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") + return nil, errors.New("tls: ECDHE RSA requires a RSA server key") } default: - return nil, errors.New("unknown ECDHE signature algorithm") + return nil, errors.New("tls: 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()) + return nil, errors.New("tls: failed to sign ECDHE parameters: " + err.Error()) } skx := new(serverKeyExchangeMsg) @@ -354,28 +354,28 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell case signatureECDSA: pubKey, ok := cert.PublicKey.(*ecdsa.PublicKey) if !ok { - return errors.New("ECDHE ECDSA requires a ECDSA server public key") + return errors.New("tls: 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") + return errors.New("tls: ECDSA signature contained zero or negative values") } if !ecdsa.Verify(pubKey, digest, ecdsaSig.R, ecdsaSig.S) { - return errors.New("ECDSA verification failure") + return errors.New("tls: ECDSA verification failure") } case signatureRSA: pubKey, ok := cert.PublicKey.(*rsa.PublicKey) if !ok { - return errors.New("ECDHE RSA requires a RSA server public key") + return errors.New("tls: 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 errors.New("tls: unknown ECDHE signature algorithm") } return nil @@ -383,7 +383,7 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell 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") + return nil, nil, errors.New("tls: missing ServerKeyExchange message") } priv, mx, my, err := elliptic.GenerateKey(ka.curve, config.rand()) if err != nil { diff --git a/libgo/go/crypto/tls/prf.go b/libgo/go/crypto/tls/prf.go index 747b817..5833fc1 100644 --- a/libgo/go/crypto/tls/prf.go +++ b/libgo/go/crypto/tls/prf.go @@ -85,7 +85,7 @@ func prf30(result, secret, label, seed []byte) { done := 0 i := 0 - // RFC5246 section 6.3 says that the largest PRF output needed is 128 + // RFC 5246 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. diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateOnce b/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateOnce new file mode 100644 index 0000000..00d35f4 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateOnce @@ -0,0 +1,251 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./| +00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........| +00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....| +00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............| +00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................| +00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................| +00000080 03 ff 01 00 01 00 00 12 00 00 |..........| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 fa 71 0e 3c 35 |....Y...U...q.<5| +00000010 33 cc 51 25 19 cf fe c4 ef c8 2d ec 88 75 a9 1c |3.Q%......-..u..| +00000020 6a e4 f3 b4 3d fd 74 cc e1 71 71 20 de 14 e5 21 |j...=.t..qq ...!| +00000030 84 17 62 62 4f 44 e7 c2 d6 00 07 d2 63 f8 b0 32 |..bbOD......c..2| +00000040 e0 12 d3 cb 69 1f d8 ed 5d 43 89 86 c0 2f 00 00 |....i...]C.../..| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 71 0b 00 02 6d 00 02 6a 00 02 67 30 82 02 |..q...m..j..g0..| +00000070 63 30 82 01 cc a0 03 02 01 02 02 09 00 a2 73 00 |c0............s.| +00000080 0c 81 00 cb f3 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....| +00000090 01 0b 05 00 30 2b 31 17 30 15 06 03 55 04 0a 13 |....0+1.0...U...| +000000a0 0e 47 6f 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 |.Google TESTING1| +000000b0 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo| +000000c0 74 30 1e 17 0d 31 35 30 31 30 31 30 30 30 30 30 |t0...15010100000| +000000d0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000| +000000e0 5a 30 26 31 17 30 15 06 03 55 04 0a 13 0e 47 6f |Z0&1.0...U....Go| +000000f0 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 0b 30 09 |ogle TESTING1.0.| +00000100 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...| +00000110 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0| +00000120 81 89 02 81 81 00 af 87 88 f6 20 1b 95 65 6c 14 |.......... ..el.| +00000130 ab 44 05 af 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f |.D..;E...m..cM..| +00000140 fe 6a 62 35 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 |.jb5..J..|..%^zd| +00000150 31 66 00 ba f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 |1f.......k.v.._A| +00000160 cb 6e 56 15 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 |.nV.....<.9!f=+.| +00000170 d1 bc db 1c c0 a7 da b7 ca ad ba da cb d5 21 50 |..............!P| +00000180 ec de 8d ab d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 |.....k.K......l.| +00000190 b1 44 84 bd 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef |.D..!..}..M.....| +000001a0 fa d6 09 47 f2 fb 02 03 01 00 01 a3 81 93 30 81 |...G..........0.| +000001b0 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........| +000001c0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.| +000001d0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......| +000001e0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.| +000001f0 06 03 55 1d 0e 04 12 04 10 12 50 8d 89 6f 1b d1 |..U.......P..o..| +00000200 dc 54 4d 6e cb 69 5e 06 f4 30 1b 06 03 55 1d 23 |.TMn.i^..0...U.#| +00000210 04 14 30 12 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea |..0....=..f..@..| +00000220 b4 03 78 48 1a 41 30 19 06 03 55 1d 11 04 12 30 |..xH.A0...U....0| +00000230 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan| +00000240 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........| +00000250 03 81 81 00 92 7c af 91 55 12 18 96 59 31 a6 48 |.....|..U...Y1.H| +00000260 40 d5 2d d5 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d |@.-........|..0}| +00000270 3c dc 76 da 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b |<.v.O=...-3$k.{.| +00000280 67 59 11 21 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 |gY.!...w...n.-.5| +00000290 fa 64 5f 22 3e 63 10 6b be ff 14 86 6d 0d f0 15 |.d_">c.k....m...| +000002a0 31 a8 14 38 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 |1..8.;..,...Qv..| +000002b0 4f dd db 9b 84 04 86 40 fa 51 dd ba b4 8d eb e3 |O......@.Q......| +000002c0 46 de 46 b9 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea |F.F.O.....A4....| +000002d0 b0 ab 39 18 16 03 03 00 cd 0c 00 00 c9 03 00 17 |..9.............| +000002e0 41 04 71 a0 a9 f0 31 52 0b a2 5f 44 b1 48 a6 dc |A.q...1R.._D.H..| +000002f0 b7 b8 bb a3 59 13 06 46 73 37 b1 9d f6 5a 42 49 |....Y..Fs7...ZBI| +00000300 a7 e4 3c 26 64 ed 26 41 f9 76 d5 88 ad b5 2f 12 |..<&d.&A.v..../.| +00000310 ce 02 34 b8 85 36 ee cd a1 dc d9 d7 4b ed d2 81 |..4..6......K...| +00000320 82 1e 04 01 00 80 86 91 0e 05 48 de 2b 45 0a 9d |..........H.+E..| +00000330 72 33 44 73 98 f3 0e 0f 4c 0b aa c0 6b 02 34 83 |r3Ds....L...k.4.| +00000340 0c e1 53 04 89 47 21 22 de 09 5e d0 b3 d9 8b 53 |..S..G!"..^....S| +00000350 62 b0 bf c6 dd fe d3 ed d6 2e ac a0 64 9d a4 07 |b...........d...| +00000360 1f a9 d5 89 5f 62 7f e0 b1 9b e2 ef 3e 36 89 70 |...._b......>6.p| +00000370 3e 7c 0a e7 8c cb c3 a8 e0 91 d9 bd 6e 3d be 0e |>|..........n=..| +00000380 a2 8c ab 46 1b 07 24 40 da a5 e3 0b b1 6a 9f 28 |...F..$@.....j.(| +00000390 c7 4f e8 d0 a3 57 e1 5c f2 34 07 aa 77 28 91 a0 |.O...W.\.4..w(..| +000003a0 7e d6 36 2c c3 1a 16 03 03 00 04 0e 00 00 00 |~.6,...........| +>>> Flow 3 (client to server) +00000000 16 03 03 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..| +00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.| +00000020 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.| +00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I| +00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 03 00 01 |..h.A.Vk.Z......| +00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 53 c5 |.....(........S.| +00000060 60 30 29 1d 8a 38 57 f3 6d d1 f4 e1 ec 3e 79 d1 |`0)..8W.m....>y.| +00000070 79 d3 b8 7f 4e 71 41 d6 72 fa c0 cd 53 92 |y...NqA.r...S.| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 28 86 be df d2 27 |..........(....'| +00000010 8b 37 77 eb 0b e4 6e 38 5c 27 56 48 bb b5 f2 be |.7w...n8\'VH....| +00000020 43 e5 f7 32 d2 d3 a1 d7 4e 6a 3c 76 17 94 c1 b0 |C..2....Nj<v....| +00000030 06 af 67 |..g| +>>> Flow 5 (client to server) +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 17 22 06 |..............".| +00000010 f7 50 b5 6f 65 e0 dd f9 b6 bc 50 b7 91 c9 54 5c |.P.oe.....P...T\| +00000020 4e 2f cc |N/.| +>>> Flow 6 (server to client) +00000000 16 03 03 00 1c 86 be df d2 27 8b 37 78 c8 e7 d6 |.........'.7x...| +00000010 4b e4 60 9e 4c b0 28 79 d9 7a 78 58 d8 27 76 18 |K.`.L.(y.zxX.'v.| +00000020 a3 |.| +>>> Flow 7 (client to server) +00000000 16 03 03 00 a9 00 00 00 00 00 00 00 02 a7 17 56 |...............V| +00000010 8e ea 2e fc 76 06 40 b2 fa 10 71 62 68 b9 14 e6 |....v.@...qbh...| +00000020 09 6d 63 86 d1 6b 87 3a c4 84 15 77 68 f8 85 ec |.mc..k.:...wh...| +00000030 55 49 3c c5 c1 be 24 85 0c 38 4b 66 a8 5f 33 f9 |UI<...$..8Kf._3.| +00000040 a3 e5 d1 36 fd 25 ba 9d 54 1f 4c df 66 09 a7 08 |...6.%..T.L.f...| +00000050 8d 7c a4 7e d4 5d c2 11 77 7b 48 7a 32 f7 88 0a |.|.~.]..w{Hz2...| +00000060 51 5f 6a 26 e2 11 88 01 5b b6 8e 6a aa 18 79 85 |Q_j&....[..j..y.| +00000070 6a 0e 31 1f 33 5e 34 fd e9 1c 84 7c ea 6c 78 5d |j.1.3^4....|.lx]| +00000080 0e d2 df c0 8c 92 3d 48 fc 9e 47 18 2a a7 1e e3 |......=H..G.*...| +00000090 9b 89 6f 30 d0 fd 0a cd 4c b9 d9 89 b6 72 53 54 |..o0....L....rST| +000000a0 3e 02 c3 d0 68 b0 4e 40 06 86 cd 8e 87 53 |>...h.N@.....S| +>>> Flow 8 (server to client) +00000000 16 03 03 00 89 86 be df d2 27 8b 37 79 29 01 95 |.........'.7y)..| +00000010 8c 13 0f f0 6e 8b 00 0c 1e 1a 36 73 b6 96 ad e1 |....n.....6s....| +00000020 40 80 6d 68 f3 41 a9 a1 85 ca 86 81 73 6c fc 49 |@.mh.A......sl.I| +00000030 b4 61 76 27 0f cd 22 5f 7e a7 c1 e3 13 f6 2e da |.av'.."_~.......| +00000040 1a 15 57 1a f1 b0 be 6d 55 44 78 95 62 82 ff 6e |..W....mUDx.b..n| +00000050 bb 70 ea 24 2c bf e2 14 48 3a 07 9a 30 3a a8 88 |.p.$,...H:..0:..| +00000060 8b d6 b4 62 28 cb 30 94 54 f6 9c 15 34 e9 c4 d2 |...b(.0.T...4...| +00000070 e3 42 cf 79 1f 96 34 f3 4c 9f f2 df 6e 70 4f cd |.B.y..4.L...npO.| +00000080 68 ae e2 2c d5 b7 f3 37 86 0a f5 7c af 32 16 03 |h..,...7...|.2..| +00000090 03 02 89 86 be df d2 27 8b 37 7a 66 a9 20 cf 95 |.......'.7zf. ..| +000000a0 d1 c9 3c c6 bc 53 16 01 e2 78 7e 2b 4d 45 20 d8 |..<..S...x~+ME .| +000000b0 be da 93 9f 61 0b 34 25 f8 42 aa 0e b7 c5 a7 7a |....a.4%.B.....z| +000000c0 99 23 b5 a5 0b 39 37 48 2d 66 21 8a bd 41 11 e5 |.#...97H-f!..A..| +000000d0 79 5f 5d c1 9b 4f c2 0c fc a4 b9 ad 82 7e 7e 5b |y_]..O.......~~[| +000000e0 f6 95 46 eb b2 9e 9c 2d 58 7e c7 90 2c c4 7f 1c |..F....-X~..,...| +000000f0 cf 32 86 37 ec ab 60 71 ee 82 2b a2 95 61 8f 31 |.2.7..`q..+..a.1| +00000100 99 2d c7 f4 5f 29 e8 b6 c3 f4 81 4f 2c b6 2c 67 |.-.._).....O,.,g| +00000110 70 e5 cf d1 00 77 34 28 dc 61 cf e1 78 10 5e 64 |p....w4(.a..x.^d| +00000120 17 f7 2b 3e 74 2c 8f 42 d5 a8 c2 4e 11 48 0f 0a |..+>t,.B...N.H..| +00000130 3f 8a ea 0f 37 f5 da 8f 7f 7c 61 b3 98 d9 69 80 |?...7....|a...i.| +00000140 b5 1e c6 5c 01 ff e3 8e 45 a1 7a cb ee ea 12 d3 |...\....E.z.....| +00000150 d7 56 2e 33 8c 55 a5 94 84 f7 a1 a4 fa f3 71 f4 |.V.3.U........q.| +00000160 a3 15 f0 7e 44 c7 32 65 86 39 93 b7 df ab 6b 94 |...~D.2e.9....k.| +00000170 df 6d d8 31 72 ba d9 7b b6 8a 68 b1 c8 da e1 a0 |.m.1r..{..h.....| +00000180 4f 0f 06 6a 52 78 6e a1 57 2f 2b 6b 10 5b c1 57 |O..jRxn.W/+k.[.W| +00000190 d0 92 23 bf dc 95 f1 83 66 ce 6f ef c5 22 22 24 |..#.....f.o..""$| +000001a0 80 bd 2f 38 ff de ec 86 8b ad 81 4e fe 31 65 54 |../8.......N.1eT| +000001b0 19 94 ce 99 0f 6d 5b 1b 53 ba ad 65 a6 6a f6 27 |.....m[.S..e.j.'| +000001c0 ba e0 b7 a9 8b 80 18 71 67 f7 6c 35 5f 69 c2 19 |.......qg.l5_i..| +000001d0 08 27 03 45 5a 58 49 27 cf ec bf 18 e7 60 64 2b |.'.EZXI'.....`d+| +000001e0 47 9e 07 1a 49 ef 90 20 c7 f7 69 5c 46 92 ae 65 |G...I.. ..i\F..e| +000001f0 fa 45 9f 3b a3 4e ed cb d9 1f d9 26 18 1e bb 58 |.E.;.N.....&...X| +00000200 16 cd a5 00 df 65 73 39 82 fd 98 29 de 45 8f 70 |.....es9...).E.p| +00000210 56 e3 c6 0b 18 71 09 92 0e 69 4e b8 e7 23 4f 70 |V....q...iN..#Op| +00000220 7a 89 06 c7 78 05 04 31 7f 77 5c 68 74 f0 45 76 |z...x..1.w\ht.Ev| +00000230 e2 56 b2 de 34 e6 79 64 49 9a a8 3a b7 5b 4a d3 |.V..4.ydI..:.[J.| +00000240 5e 6d 0b f3 fb 6d 0c 2f 61 d0 71 f4 0d ed 60 2f |^m...m./a.q...`/| +00000250 61 80 c9 9b b9 e5 89 f2 64 88 52 d6 d3 aa 72 6b |a.......d.R...rk| +00000260 66 18 ae e9 df 20 40 15 b5 73 ba ac 50 b1 27 99 |f.... @..s..P.'.| +00000270 b3 17 97 56 0b 7d 25 8a 64 80 42 5c c8 b8 d5 98 |...V.}%.d.B\....| +00000280 28 16 2b ce 45 65 3d fc d8 c6 91 31 c2 d4 09 a3 |(.+.Ee=....1....| +00000290 cf 92 85 63 36 cb e2 da a3 66 fb 08 c9 bc 12 23 |...c6....f.....#| +000002a0 c8 88 7d 46 22 98 40 01 bf fb 58 84 f2 8f ad 83 |..}F".@...X.....| +000002b0 ed 79 b4 a8 3d e5 92 b7 b8 e1 d0 50 aa be 22 9c |.y..=......P..".| +000002c0 9c cb dc bd 65 59 41 3e 6f 53 89 02 30 b1 88 ca |....eYA>oS..0...| +000002d0 06 6d 8e b2 a6 75 6a d8 5a 19 65 de 27 c3 bf 70 |.m...uj.Z.e.'..p| +000002e0 49 64 13 2d 19 5d 7a ec 91 a7 f6 82 92 7d e3 7e |Id.-.]z......}.~| +000002f0 d6 65 5b d4 eb ed 58 d7 cd 41 a2 b9 d3 9e e4 a0 |.e[...X..A......| +00000300 92 bf 88 4f 0e 59 74 66 86 db 72 11 18 ad 81 24 |...O.Ytf..r....$| +00000310 6e 43 38 24 23 fb db af 92 d8 1a 2d 16 03 03 00 |nC8$#......-....| +00000320 e5 86 be df d2 27 8b 37 7b ce 01 b6 78 47 7d 3a |.....'.7{...xG}:| +00000330 ad 2e 03 8e 78 03 61 da 55 0e d4 fa 87 9d 20 25 |....x.a.U..... %| +00000340 73 1f 3b 87 7b 02 c1 a3 af ce d5 b9 9e 29 91 1b |s.;.{........)..| +00000350 58 13 c9 bc 96 95 88 f8 67 43 03 25 a3 be 5e a6 |X.......gC.%..^.| +00000360 1d ee 6e 70 4c b5 66 48 3d 7d 1a 58 8e 10 c0 68 |..npL.fH=}.X...h| +00000370 6b d8 f1 dd 83 c5 d3 c8 81 c5 6d 72 68 50 41 6f |k.........mrhPAo| +00000380 f6 20 13 f8 72 fa 82 9a 25 e4 07 10 df b7 39 90 |. ..r...%.....9.| +00000390 6a d7 d2 d7 a1 1c 31 4e b6 7c 00 bc 4d b1 a1 ff |j.....1N.|..M...| +000003a0 d0 ae 42 b1 2d 3e 8b c9 43 f4 fa fc d4 71 8f 74 |..B.->..C....q.t| +000003b0 37 23 1b bb 34 4e b6 e4 fe f1 1b ea da 08 e4 12 |7#..4N..........| +000003c0 fd 50 23 f9 8a 2d 92 eb f5 2b fc b4 e1 35 87 74 |.P#..-...+...5.t| +000003d0 44 79 0b df 6a 14 eb 20 17 ab 5b 12 a7 19 a4 4e |Dy..j.. ..[....N| +000003e0 94 70 93 57 2d bd c2 54 88 fb 19 b7 82 28 ab db |.p.W-..T.....(..| +000003f0 ca a9 19 5d 36 1b d6 fc 7d 41 2c 5b 76 ec 90 72 |...]6...}A,[v..r| +00000400 47 5b c4 ae 59 a6 16 03 03 00 46 86 be df d2 27 |G[..Y.....F....'| +00000410 8b 37 7c ed db 59 c6 0b 4e 52 c9 bc 7a 81 ed 20 |.7|..Y..NR..z.. | +00000420 00 55 02 76 15 49 9b 0b f2 81 c2 f7 25 51 61 9d |.U.v.I......%Qa.| +00000430 48 e3 d2 6f 08 ea 0c 9b 26 cc 3b 52 58 ef a0 1f |H..o....&.;RX...| +00000440 09 c3 ca e8 c2 6c 13 86 b1 94 04 f1 65 e2 de 4c |.....l......e..L| +00000450 7c ||| +>>> Flow 9 (client to server) +00000000 16 03 03 02 89 00 00 00 00 00 00 00 03 3c 0f 09 |.............<..| +00000010 9e dc 39 b8 be ab ca 53 74 05 93 12 a4 e7 bb 56 |..9....St......V| +00000020 9f e1 9f 2a 09 7d e1 74 89 ee b3 99 3c 91 c6 38 |...*.}.t....<..8| +00000030 7e 0c 5e 2d 1f 7d bd cd 1a d1 16 ab af 94 08 c6 |~.^-.}..........| +00000040 74 e3 16 12 0e 9b bc 91 95 6d 01 fd 10 00 12 c6 |t........m......| +00000050 03 96 92 08 df 50 89 ba 5c 25 ce 31 d8 b1 84 8a |.....P..\%.1....| +00000060 7d 6c cf 7f e6 9a e4 08 17 cc b8 f2 c9 8f e8 4b |}l.............K| +00000070 ab 44 4f e9 63 8c 93 71 b1 70 4a f4 29 5f ef 45 |.DO.c..q.pJ.)_.E| +00000080 68 e1 0e 31 a0 4c 96 8c 65 03 f3 48 24 48 d4 d7 |h..1.L..e..H$H..| +00000090 93 d1 17 39 8d 97 e8 d8 59 08 4b 46 82 cf a3 99 |...9....Y.KF....| +000000a0 55 36 65 a9 d8 df db d5 65 78 52 38 c2 2a 1e ec |U6e.....exR8.*..| +000000b0 65 6a f5 d5 4c 81 0c f6 e6 77 b2 68 d4 6c 32 05 |ej..L....w.h.l2.| +000000c0 ef f4 ee 0b e1 83 d0 3a cf a0 06 f2 cc 61 62 5e |.......:.....ab^| +000000d0 fa b4 19 c7 e2 99 c1 cf 02 a1 01 3d 6a e0 be 9f |...........=j...| +000000e0 82 cd e5 c8 ac e2 3e 6d 0f 60 a4 e9 9b ca cf c9 |......>m.`......| +000000f0 c1 fe 2d ef 29 ed f9 c3 11 03 9f 76 66 71 ef 24 |..-.)......vfq.$| +00000100 5f d3 29 aa 6a e1 0c b1 58 7a f3 df 92 e8 61 e2 |_.).j...Xz....a.| +00000110 41 43 ad 9d 55 a0 b0 a3 20 8d 2c 8f 34 e6 ab d3 |AC..U... .,.4...| +00000120 37 80 9e cb 27 91 69 0a ba 33 05 a1 7f 4d 7f 63 |7...'.i..3...M.c| +00000130 ed 6a c1 72 43 ec 6a 6c ac b7 87 bb 81 6e 06 fa |.j.rC.jl.....n..| +00000140 68 7a c9 33 28 59 ed 74 87 a1 6a 24 06 02 c0 21 |hz.3(Y.t..j$...!| +00000150 71 b0 27 f9 6e b3 7e 30 e9 e0 df c2 5d 63 2a dd |q.'.n.~0....]c*.| +00000160 9d e9 9c 4f 47 66 68 7e e4 8c 87 b7 f0 a8 3d b8 |...OGfh~......=.| +00000170 36 39 3e 4c 9f 55 e7 bb c7 3e 34 36 54 19 41 33 |69>L.U...>46T.A3| +00000180 61 e6 9a ae c6 91 1d fa 2d 8c 45 95 5f 95 36 79 |a.......-.E._.6y| +00000190 e9 59 7e 81 cd 7e 9e 01 fe 85 eb c8 ed 4e 93 c6 |.Y~..~.......N..| +000001a0 53 76 2d 5c 72 50 22 16 04 15 c2 cf 19 07 e6 73 |Sv-\rP"........s| +000001b0 74 d0 7b bb 68 c3 29 39 bc ab 1b 4c c9 5a 36 73 |t.{.h.)9...L.Z6s| +000001c0 55 47 7a c8 4a a7 45 fe f3 a9 94 6e ea ea cc 7d |UGz.J.E....n...}| +000001d0 d1 de f4 82 4c 14 84 f0 58 09 56 25 83 7a 23 71 |....L...X.V%.z#q| +000001e0 a1 63 e3 4e 13 78 68 41 a1 9a 55 ec 9e 37 ee c2 |.c.N.xhA..U..7..| +000001f0 7d 3f 8f 91 00 30 f2 ca 7b 13 b7 e7 fe 85 c5 aa |}?...0..{.......| +00000200 5e e3 97 2c cb d5 13 1e 83 3d c9 2a b1 21 f1 58 |^..,.....=.*.!.X| +00000210 7d 09 32 31 d6 fd 89 26 ff 72 3c f7 c4 fe 99 33 |}.21...&.r<....3| +00000220 41 82 76 05 b9 14 b1 b0 3c 41 02 74 a8 1d dd 80 |A.v.....<A.t....| +00000230 38 67 25 01 39 f7 36 fa e4 1c 7d 2f c9 7e 21 0a |8g%.9.6...}/.~!.| +00000240 30 77 1e ff fc 8a 31 ac ee 91 f0 2c b1 9a b7 5e |0w....1....,...^| +00000250 26 d0 7a 9d b4 9e 53 6b dd a6 5e 7b f0 45 99 9b |&.z...Sk..^{.E..| +00000260 2b 69 90 d4 dd 1a d0 b5 13 90 11 ac 01 f0 2f 94 |+i............/.| +00000270 5b 59 7e 7a 40 22 3a b0 d4 24 92 7d 94 bf 34 91 |[Y~z@":..$.}..4.| +00000280 f6 b9 cc c9 e5 de d3 67 6d 83 97 ee 8f 48 16 03 |.......gm....H..| +00000290 03 00 5e 00 00 00 00 00 00 00 04 dc 6f 41 98 23 |..^.........oA.#| +000002a0 d7 70 80 24 74 46 c8 45 e1 2f 43 1d b8 66 4d 0a |.p.$tF.E./C..fM.| +000002b0 03 0e d6 01 8b 92 f7 76 c1 2c 32 6c 65 60 da ab |.......v.,2le`..| +000002c0 0b 12 6d 30 1c cf de e7 ec a7 12 f9 df 6c b4 42 |..m0.........l.B| +000002d0 e7 d9 6e 6e f3 1c 10 ee 39 47 7f ec 7c ec 68 68 |..nn....9G..|.hh| +000002e0 e8 b2 70 a2 67 61 e0 b3 68 b5 91 9f 1a e0 c5 af |..p.ga..h.......| +000002f0 e3 16 03 03 00 a0 00 00 00 00 00 00 00 05 6b 56 |..............kV| +00000300 3d 5e 4e f1 2c 30 e2 91 24 5c b1 5f d3 7d 3e dc |=^N.,0..$\._.}>.| +00000310 ba 98 e1 9f 72 98 2b 0e 11 07 d1 ea 14 d5 73 25 |....r.+.......s%| +00000320 d2 cf 8e bc a5 ea 93 a7 32 ab 94 83 1e ea c5 62 |........2......b| +00000330 06 79 bb ab 4c a0 cf fb 51 3b 7b f0 11 5e ae 50 |.y..L...Q;{..^.P| +00000340 23 cb ff 86 03 3d a5 66 b9 c4 35 c2 12 f2 98 85 |#....=.f..5.....| +00000350 77 ba af 3b d5 dd f2 cd 58 09 29 26 08 cd 4a ed |w..;....X.)&..J.| +00000360 ac af 57 ab 27 1a 40 ef 10 57 d1 ad 06 34 be ed |..W.'.@..W...4..| +00000370 fe 88 1d 09 4a 81 8a da e7 ef fa 27 71 ab 2b 3f |....J......'q.+?| +00000380 21 91 5f 1a dc 50 a4 f0 58 bd aa af 75 4e 25 2a |!._..P..X...uN%*| +00000390 2c 55 e5 57 c6 ab 14 03 03 00 19 00 00 00 00 00 |,U.W............| +000003a0 00 00 06 5d 8a 3e 8e 55 e4 9d c0 6a de 91 c6 96 |...].>.U...j....| +000003b0 6e 17 54 a5 16 03 03 00 28 00 00 00 00 00 00 00 |n.T.....(.......| +000003c0 00 d5 45 5d 11 af e2 b6 f1 a8 e5 ed 58 80 54 ce |..E]........X.T.| +000003d0 b3 db dc 97 b3 86 c0 83 f9 3b 7c b5 ad 21 f8 cf |.........;|..!..| +000003e0 9a |.| +>>> Flow 10 (server to client) +00000000 14 03 03 00 19 86 be df d2 27 8b 37 7d 85 70 b7 |.........'.7}.p.| +00000010 a7 98 89 36 01 b4 a8 6f cb 14 0f dd ac 08 16 03 |...6...o........| +00000020 03 00 28 75 41 a9 ef 1c 88 59 4e 84 15 29 a4 75 |..(uA....YN..).u| +00000030 e6 66 01 3f a1 b7 ff 69 04 b6 08 99 c9 5e 57 60 |.f.?...i.....^W`| +00000040 ea 76 21 94 06 e4 32 95 e1 4c d7 17 03 03 00 21 |.v!...2..L.....!| +00000050 75 41 a9 ef 1c 88 59 4f c8 5d 4e bd 42 52 ec 50 |uA....YO.]N.BR.P| +00000060 2f 28 4f 87 da bc f0 df a8 93 14 b7 6f a0 7f a2 |/(O.........o...| +00000070 c5 |.| +>>> Flow 11 (client to server) +00000000 15 03 03 00 1a 00 00 00 00 00 00 00 01 92 8a f2 |................| +00000010 9a d1 c9 1e 68 15 2d 6b 9a a7 f8 21 78 87 89 |....h.-k...!x..| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwice b/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwice new file mode 100644 index 0000000..185dc65 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwice @@ -0,0 +1,409 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./| +00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........| +00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....| +00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............| +00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................| +00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................| +00000080 03 ff 01 00 01 00 00 12 00 00 |..........| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 bb b7 b5 ee 8b |....Y...U.......| +00000010 b7 92 40 96 01 65 93 09 a0 63 77 b3 35 74 0a 73 |..@..e...cw.5t.s| +00000020 db e8 4a 9c d4 95 4b 2a f9 43 1e 20 d6 5a ed d1 |..J...K*.C. .Z..| +00000030 05 f0 61 aa 45 ae 0e 92 03 87 1b a6 0a 1a 83 a1 |..a.E...........| +00000040 bd 4f c3 81 79 e8 56 10 5d 08 7b 6d c0 2f 00 00 |.O..y.V.].{m./..| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 71 0b 00 02 6d 00 02 6a 00 02 67 30 82 02 |..q...m..j..g0..| +00000070 63 30 82 01 cc a0 03 02 01 02 02 09 00 a2 73 00 |c0............s.| +00000080 0c 81 00 cb f3 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....| +00000090 01 0b 05 00 30 2b 31 17 30 15 06 03 55 04 0a 13 |....0+1.0...U...| +000000a0 0e 47 6f 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 |.Google TESTING1| +000000b0 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo| +000000c0 74 30 1e 17 0d 31 35 30 31 30 31 30 30 30 30 30 |t0...15010100000| +000000d0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000| +000000e0 5a 30 26 31 17 30 15 06 03 55 04 0a 13 0e 47 6f |Z0&1.0...U....Go| +000000f0 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 0b 30 09 |ogle TESTING1.0.| +00000100 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...| +00000110 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0| +00000120 81 89 02 81 81 00 af 87 88 f6 20 1b 95 65 6c 14 |.......... ..el.| +00000130 ab 44 05 af 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f |.D..;E...m..cM..| +00000140 fe 6a 62 35 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 |.jb5..J..|..%^zd| +00000150 31 66 00 ba f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 |1f.......k.v.._A| +00000160 cb 6e 56 15 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 |.nV.....<.9!f=+.| +00000170 d1 bc db 1c c0 a7 da b7 ca ad ba da cb d5 21 50 |..............!P| +00000180 ec de 8d ab d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 |.....k.K......l.| +00000190 b1 44 84 bd 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef |.D..!..}..M.....| +000001a0 fa d6 09 47 f2 fb 02 03 01 00 01 a3 81 93 30 81 |...G..........0.| +000001b0 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........| +000001c0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.| +000001d0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......| +000001e0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.| +000001f0 06 03 55 1d 0e 04 12 04 10 12 50 8d 89 6f 1b d1 |..U.......P..o..| +00000200 dc 54 4d 6e cb 69 5e 06 f4 30 1b 06 03 55 1d 23 |.TMn.i^..0...U.#| +00000210 04 14 30 12 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea |..0....=..f..@..| +00000220 b4 03 78 48 1a 41 30 19 06 03 55 1d 11 04 12 30 |..xH.A0...U....0| +00000230 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan| +00000240 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........| +00000250 03 81 81 00 92 7c af 91 55 12 18 96 59 31 a6 48 |.....|..U...Y1.H| +00000260 40 d5 2d d5 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d |@.-........|..0}| +00000270 3c dc 76 da 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b |<.v.O=...-3$k.{.| +00000280 67 59 11 21 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 |gY.!...w...n.-.5| +00000290 fa 64 5f 22 3e 63 10 6b be ff 14 86 6d 0d f0 15 |.d_">c.k....m...| +000002a0 31 a8 14 38 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 |1..8.;..,...Qv..| +000002b0 4f dd db 9b 84 04 86 40 fa 51 dd ba b4 8d eb e3 |O......@.Q......| +000002c0 46 de 46 b9 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea |F.F.O.....A4....| +000002d0 b0 ab 39 18 16 03 03 00 cd 0c 00 00 c9 03 00 17 |..9.............| +000002e0 41 04 b5 fe 7d 68 cd 5a b7 bf 61 10 81 dc 92 23 |A...}h.Z..a....#| +000002f0 d0 82 13 fb 71 6f 39 48 f9 87 f8 f7 a0 3a cd 18 |....qo9H.....:..| +00000300 85 d7 4d 66 88 9d 39 8d 6d 53 a1 a3 0d 00 b0 0f |..Mf..9.mS......| +00000310 14 64 1b 72 2d 89 5c 93 6f 3c ed c9 82 20 3d 2f |.d.r-.\.o<... =/| +00000320 d0 7f 04 01 00 80 42 24 14 6e cf 78 ea 30 90 1e |......B$.n.x.0..| +00000330 4e 99 bf ca 98 9c 2f 24 98 c2 a2 b3 f8 34 49 22 |N...../$.....4I"| +00000340 35 16 11 03 79 3b a8 10 a3 fa d8 5e 17 9d f9 50 |5...y;.....^...P| +00000350 0a 3b 0b b5 b2 0f 90 18 c1 f5 6f 89 84 04 e2 f0 |.;........o.....| +00000360 b0 04 2f 3e 78 d3 de 31 9e 6e 3b b8 c7 f5 cc 4f |../>x..1.n;....O| +00000370 4e ad fe 76 d2 6d 23 31 94 56 b1 d8 df 0d 9b c5 |N..v.m#1.V......| +00000380 f7 9e 9c a7 2a 47 e4 c8 20 08 fc 6c d5 29 cd 36 |....*G.. ..l.).6| +00000390 88 83 c5 59 33 6d 1f 0b f9 98 65 fa cb f7 89 2d |...Y3m....e....-| +000003a0 90 3a 40 8a 31 7e 16 03 03 00 04 0e 00 00 00 |.:@.1~.........| +>>> Flow 3 (client to server) +00000000 16 03 03 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..| +00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.| +00000020 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.| +00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I| +00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 03 00 01 |..h.A.Vk.Z......| +00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 fa e7 |.....(..........| +00000060 ff 47 50 7a 68 0d 20 f6 9f 2a b5 bc f4 21 c1 72 |.GPzh. ..*...!.r| +00000070 07 4c e5 07 2c 07 e5 1e d7 fa 07 01 83 68 |.L..,........h| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 28 b7 93 18 5b 36 |..........(...[6| +00000010 18 ce 97 17 75 40 15 17 1f 0e 0d 99 fd 66 fa 89 |....u@.......f..| +00000020 db b7 97 95 a9 45 90 07 6e 82 0e 67 4f 01 58 ec |.....E..n..gO.X.| +00000030 94 d7 ad |...| +>>> Flow 5 (client to server) +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 21 2b 7b |.............!+{| +00000010 62 ac e4 37 d6 77 19 89 77 1c 6a ce 40 c1 9d 71 |b..7.w..w.j.@..q| +00000020 5a 23 f0 |Z#.| +>>> Flow 6 (server to client) +00000000 16 03 03 00 1c b7 93 18 5b 36 18 ce 98 4a 49 69 |........[6...JIi| +00000010 f4 dd 35 f2 93 3b c6 4e d5 25 51 34 38 23 ea 74 |..5..;.N.%Q48#.t| +00000020 84 |.| +>>> Flow 7 (client to server) +00000000 16 03 03 00 a9 00 00 00 00 00 00 00 02 65 09 7a |.............e.z| +00000010 d5 9b 32 0b cd 10 ea 2c b6 d8 be ce db 3f a4 38 |..2....,.....?.8| +00000020 a7 37 a3 95 ed 05 a7 c1 28 69 7a 13 50 07 ab 19 |.7......(iz.P...| +00000030 52 d7 29 fe 49 80 f0 ef ea 17 ac 20 f9 62 51 72 |R.).I...... .bQr| +00000040 8d c0 17 62 03 cf bb 80 f8 6f 1b 74 f1 85 45 96 |...b.....o.t..E.| +00000050 49 55 56 b0 7a dd 9b 5a f1 3f 1a e7 96 cd 21 ec |IUV.z..Z.?....!.| +00000060 85 6f b9 9d 0f e3 f6 55 9b b8 a7 e1 77 ad 53 0b |.o.....U....w.S.| +00000070 98 90 ac 5d cf 31 0f 86 69 04 d8 e9 5e fc ea a8 |...].1..i...^...| +00000080 a8 b7 a2 d8 0f ea 4f e5 ac f2 b2 c0 59 29 ba 53 |......O.....Y).S| +00000090 af 1e 81 08 be 02 46 a7 b8 6f 2a b4 86 47 5d 8e |......F..o*..G].| +000000a0 72 a6 64 84 7e 76 31 9c 31 fb 59 b7 da 15 |r.d.~v1.1.Y...| +>>> Flow 8 (server to client) +00000000 16 03 03 00 89 b7 93 18 5b 36 18 ce 99 4a 72 26 |........[6...Jr&| +00000010 ab cb a4 70 60 0f 7a 02 62 28 f3 10 54 77 a7 33 |...p`.z.b(..Tw.3| +00000020 32 a6 29 c8 8d 18 48 8f 9d 45 6e 7e 06 07 ca b3 |2.)...H..En~....| +00000030 b6 45 eb ac f2 41 f1 d9 19 9e 30 1f c0 18 40 1c |.E...A....0...@.| +00000040 55 09 4d f2 23 75 2f 2f c8 b7 46 63 05 d1 73 c0 |U.M.#u//..Fc..s.| +00000050 02 71 de 5e 4a 84 92 3d 9a b9 68 62 31 91 7d 23 |.q.^J..=..hb1.}#| +00000060 43 e3 4b 00 98 2e 01 12 f4 1f fa 4c aa 91 a0 ca |C.K........L....| +00000070 9c a0 d9 6b 7f 5c b3 f4 8d e2 3a 54 eb e9 82 44 |...k.\....:T...D| +00000080 21 54 ac 85 86 39 b8 df 23 64 2a 0c 3e 1d 16 03 |!T...9..#d*.>...| +00000090 03 02 89 b7 93 18 5b 36 18 ce 9a 1c ae 99 12 58 |......[6.......X| +000000a0 12 fa ef da 77 04 7f b5 42 68 b1 59 64 50 92 2b |....w...Bh.YdP.+| +000000b0 a0 21 b7 b3 4c f8 c2 cc 75 5a d0 85 50 95 f4 1b |.!..L...uZ..P...| +000000c0 c9 b2 1f 53 94 4c fd 6d 18 ad 1a 0d 24 9f fb 4c |...S.L.m....$..L| +000000d0 19 13 5a 74 f2 e2 59 dd 1b d8 67 bc d9 d0 da ab |..Zt..Y...g.....| +000000e0 a7 7f 8e ca e0 09 28 59 18 8d a1 8a c9 c3 2e 76 |......(Y.......v| +000000f0 b9 0d 2f 56 5f c4 77 07 17 ac 62 26 a1 91 50 ee |../V_.w...b&..P.| +00000100 60 45 aa a0 8a d9 1a 13 65 68 c8 cf ca 0c 50 3e |`E......eh....P>| +00000110 9f 39 62 02 12 ea b4 ed e2 6c 0e 28 32 d7 fb ec |.9b......l.(2...| +00000120 fc 6d e4 0a 14 1d 88 00 a8 c0 57 1e be 78 fd 18 |.m........W..x..| +00000130 6e 40 70 37 2e f5 3b 52 59 03 02 bf 27 18 c8 00 |n@p7..;RY...'...| +00000140 58 8f 5e d8 a8 7c 4c 54 83 4a fe f3 dc f8 19 2a |X.^..|LT.J.....*| +00000150 00 ed 96 93 0e e4 45 58 8f 41 99 0d 93 f5 6c a4 |......EX.A....l.| +00000160 4e 62 f2 4b 9a cb 69 30 5a 4b 36 45 f2 d2 c1 62 |Nb.K..i0ZK6E...b| +00000170 f9 1c c4 c3 b2 94 b3 17 1a ed d8 57 ba b7 79 a1 |...........W..y.| +00000180 a2 2e 5a 18 79 36 0b 54 ee 2c 2c 3b 62 96 5d e5 |..Z.y6.T.,,;b.].| +00000190 3c 74 0e be 52 6f 06 7c 93 05 86 0f d6 1d d0 ee |<t..Ro.|........| +000001a0 f9 ac 67 50 a6 d3 36 f7 5f 0b 3f 44 3b fc 4b 79 |..gP..6._.?D;.Ky| +000001b0 b7 29 04 6c 37 18 2a 04 bf f4 3e 1a 53 f3 93 e5 |.).l7.*...>.S...| +000001c0 f2 b7 b1 4b ed 19 5a 2f 40 d1 f2 91 49 0b 8b f6 |...K..Z/@...I...| +000001d0 21 0b 20 01 ce 0f a8 f1 44 3f 5e b1 89 1a 15 9f |!. .....D?^.....| +000001e0 4c c5 93 6b 68 93 ab 67 b5 1d 10 fa 22 53 e3 0f |L..kh..g...."S..| +000001f0 c7 63 d0 32 b7 52 c6 2e b7 47 a4 1a b4 ab 35 a9 |.c.2.R...G....5.| +00000200 b0 0e cd f6 8c e7 54 6c 77 7b 5c 6c c2 b3 02 89 |......Tlw{\l....| +00000210 74 f7 b1 61 91 dc 01 3a 68 d9 81 78 21 95 b1 67 |t..a...:h..x!..g| +00000220 36 2d 2a d6 c4 96 0d 7b e0 44 83 cd 52 e4 05 36 |6-*....{.D..R..6| +00000230 a4 1d 2a 24 e8 cc 76 d7 66 2f 32 ef 8f 70 ef 26 |..*$..v.f/2..p.&| +00000240 90 73 2e e6 b4 53 91 13 5b 5e 15 51 15 56 e9 43 |.s...S..[^.Q.V.C| +00000250 22 9a b6 55 3d 94 00 35 73 41 12 fc 8a 0b fd 89 |"..U=..5sA......| +00000260 7c 00 14 0d b8 f6 76 d0 ac 33 1d e4 73 49 e9 a2 ||.....v..3..sI..| +00000270 09 69 e1 f1 a7 92 48 ee 2e fc ef 13 09 7c a7 72 |.i....H......|.r| +00000280 eb 4c 15 39 17 6e cd 71 c0 e9 48 06 43 09 19 39 |.L.9.n.q..H.C..9| +00000290 72 b0 9c f8 0e 75 af a8 eb 25 96 36 75 68 16 8f |r....u...%.6uh..| +000002a0 e8 f6 66 56 66 63 b0 52 47 74 55 af c8 7a 07 dc |..fVfc.RGtU..z..| +000002b0 d0 8b bf 51 6e bc 77 fa 8a 03 43 0c 5a 47 fb c7 |...Qn.w...C.ZG..| +000002c0 be b3 ef b5 ad 24 48 40 6c 4b 03 41 dd 7c 3e 6e |.....$H@lK.A.|>n| +000002d0 25 01 4b 45 ce ad d7 23 3a 6c 33 0b f1 7a 44 07 |%.KE...#:l3..zD.| +000002e0 7e c8 bd 52 a5 a8 30 91 95 3e 4d 42 07 67 57 fb |~..R..0..>MB.gW.| +000002f0 c0 4a ed 9f 76 21 8e df fb f6 a4 0a 08 1e 5b c6 |.J..v!........[.| +00000300 3e a3 8c 47 a4 4d 41 2b e6 8f 42 43 cd ef a8 f1 |>..G.MA+..BC....| +00000310 88 f2 b3 46 eb 8a 24 a3 98 a2 d7 d2 16 03 03 00 |...F..$.........| +00000320 e5 b7 93 18 5b 36 18 ce 9b 62 57 ae 22 62 34 88 |....[6...bW."b4.| +00000330 41 e1 7e 2a 4a 07 b4 b8 aa 80 32 f5 93 4c 58 79 |A.~*J.....2..LXy| +00000340 82 51 d4 b8 c8 5b d2 99 a3 18 43 aa c2 14 bf 65 |.Q...[....C....e| +00000350 e8 90 8d 46 69 d5 fa 34 e4 1a 47 06 dc 1a ae e9 |...Fi..4..G.....| +00000360 40 b2 2e 7e 5e 74 f7 72 4d a9 e2 b7 52 b4 bb dc |@..~^t.rM...R...| +00000370 06 e6 50 7e ef 42 8f 72 08 63 f9 ec 9e 13 36 0f |..P~.B.r.c....6.| +00000380 d4 95 72 2b ff a5 6d 4b 1b db d6 b3 25 50 f0 dd |..r+..mK....%P..| +00000390 e3 89 f5 c1 c0 3f aa 6c f0 a7 30 5d 56 76 77 b6 |.....?.l..0]Vvw.| +000003a0 24 8f 93 fd 49 8c 73 1e f7 5c 5c 3a f3 0d 5e 89 |$...I.s..\\:..^.| +000003b0 a4 bb 48 8a 82 ed 01 a6 2d eb b1 fe d2 6e 4e 88 |..H.....-....nN.| +000003c0 1d 06 b6 f5 d8 41 86 40 fe 45 3e ef 35 9b 88 df |.....A.@.E>.5...| +000003d0 48 af e0 05 33 4e 13 15 8b b6 5a 8e 5c f8 2a 59 |H...3N....Z.\.*Y| +000003e0 14 6d 4a 79 75 48 e4 9d 16 4f 6f 65 9c c3 40 1e |.mJyuH...Ooe..@.| +000003f0 7c 72 60 ce b9 f8 61 3b ff 34 81 94 01 aa b3 59 ||r`...a;.4.....Y| +00000400 72 d2 1e 5f fe 7f 16 03 03 00 46 b7 93 18 5b 36 |r.._......F...[6| +00000410 18 ce 9c c8 c9 b2 10 f1 39 bb f0 80 a9 0b 68 76 |........9.....hv| +00000420 2b 60 0b c5 f3 eb 16 72 b5 4c c9 42 96 39 bf c1 |+`.....r.L.B.9..| +00000430 94 87 f0 47 80 34 11 e2 1c 4c fc 26 d6 4b 00 49 |...G.4...L.&.K.I| +00000440 ef 73 00 4e ab 61 d6 1f 89 2c 7e f2 5c ea 6b 5c |.s.N.a...,~.\.k\| +00000450 50 |P| +>>> Flow 9 (client to server) +00000000 16 03 03 02 89 00 00 00 00 00 00 00 03 c2 d4 9b |................| +00000010 19 c8 b6 76 fb ef e4 b2 f7 97 c7 80 f5 e2 b4 3c |...v...........<| +00000020 bd b7 b8 25 da 54 52 a7 f8 38 0d 48 c0 13 19 82 |...%.TR..8.H....| +00000030 17 3c ff d2 c0 8f bd 76 5d 16 39 db a7 51 3f b1 |.<.....v].9..Q?.| +00000040 72 b6 59 e4 8c 6c f5 33 de 78 15 8d 64 cf 55 c6 |r.Y..l.3.x..d.U.| +00000050 47 e3 0b 30 06 e1 6c 2d e1 e0 7a e1 0a da dd 0d |G..0..l-..z.....| +00000060 60 5b 06 28 a8 94 14 a3 cc 91 96 8d 2b 71 af ff |`[.(........+q..| +00000070 c2 32 e2 19 77 96 f3 5b 53 3a d3 29 51 c2 54 98 |.2..w..[S:.)Q.T.| +00000080 f3 00 8e 9a fe ef bb ea 06 27 58 54 3c c8 67 dc |.........'XT<.g.| +00000090 f3 41 01 77 de 25 b4 54 53 67 64 41 b3 ae 2b c2 |.A.w.%.TSgdA..+.| +000000a0 57 cd 74 14 3c 46 a7 70 ec a8 bc 0e 05 46 ce fc |W.t.<F.p.....F..| +000000b0 c8 54 4d 23 25 b9 e0 45 fa 1e 1b 2c f1 d0 da 66 |.TM#%..E...,...f| +000000c0 3c 00 e5 b3 f5 f9 ff 64 75 82 f9 dd c2 3f 42 46 |<......du....?BF| +000000d0 27 ca 72 a2 f7 6c 4e bf 98 05 e6 99 b5 7b 60 33 |'.r..lN......{`3| +000000e0 99 e8 7a 7c 91 41 64 cd 96 60 f2 f6 c8 bd 4f 35 |..z|.Ad..`....O5| +000000f0 5f 6f 43 11 b0 94 3c 98 bc 58 15 7e 52 01 ba cf |_oC...<..X.~R...| +00000100 71 f4 0a fb 85 0a 24 13 0c 4a 53 55 77 92 91 cd |q.....$..JSUw...| +00000110 ce 39 7e 07 2f 4f ba 47 ca bd 67 5b ce 5a 04 03 |.9~./O.G..g[.Z..| +00000120 ff 86 0a 82 80 b9 42 b8 4c e3 ce 73 b2 4a 5a 4b |......B.L..s.JZK| +00000130 f5 f2 44 d8 e5 01 30 c8 2e ce 4f 62 2d 34 9c d6 |..D...0...Ob-4..| +00000140 57 20 db 37 20 66 03 b6 4d a7 0f 75 30 d8 ad 2f |W .7 f..M..u0../| +00000150 63 f7 4e 24 ec 68 e0 a2 a9 b1 3d 68 e5 c1 8b d8 |c.N$.h....=h....| +00000160 19 dd 40 33 c6 5c 57 3b 22 5a 9c 24 fe 2f 92 54 |..@3.\W;"Z.$./.T| +00000170 0f e8 85 74 06 72 59 ab 1d b8 5d 31 91 ed 05 51 |...t.rY...]1...Q| +00000180 61 c6 43 3d 81 f4 47 c3 80 17 4d 1b 08 c4 85 1b |a.C=..G...M.....| +00000190 b7 37 b0 cf 5c 73 5f 56 0f 5a b5 21 21 46 e3 df |.7..\s_V.Z.!!F..| +000001a0 e6 cb 9d ac ab 16 c0 b1 b8 2a 4a 5b a7 2d 7a 00 |.........*J[.-z.| +000001b0 9f 9d 76 57 ab 20 ea 80 8a 7a ca 14 45 d7 4e 1b |..vW. ...z..E.N.| +000001c0 c8 7c b8 c6 82 fc 40 b2 b4 7d f1 74 7d b5 2a 90 |.|....@..}.t}.*.| +000001d0 01 83 d4 d1 26 63 d7 39 69 b1 33 5f 7e 54 de f7 |....&c.9i.3_~T..| +000001e0 08 3d 62 3b da 57 0d d4 48 99 9a 3e 99 e5 b0 6b |.=b;.W..H..>...k| +000001f0 25 45 38 36 aa 7a bb 81 7d 0b dd 1d 50 c4 17 68 |%E86.z..}...P..h| +00000200 4b a7 f7 2f d8 cd 97 a6 ea 24 9b 34 69 9e 7d ad |K../.....$.4i.}.| +00000210 6a 17 23 d8 36 61 cf 85 74 47 18 5b fd cd 72 ac |j.#.6a..tG.[..r.| +00000220 c2 a2 b4 53 e3 5d 25 f7 bb b6 95 99 a0 e5 05 38 |...S.]%........8| +00000230 0a 52 32 f6 7d a6 30 5c 11 6b 8a 7b af ec a2 9b |.R2.}.0\.k.{....| +00000240 b8 f1 85 6d a8 b7 79 61 42 60 4a 35 73 fb d5 2c |...m..yaB`J5s..,| +00000250 1f 84 5c d9 c9 23 10 e8 a4 2c 56 fd f4 22 1a 7a |..\..#...,V..".z| +00000260 f3 b2 c5 69 8b c9 d1 d5 45 c8 65 59 fc ab d9 d3 |...i....E.eY....| +00000270 7d ab c3 fe bc da 6d a3 cd 0c 83 32 70 65 c7 7f |}.....m....2pe..| +00000280 8c 83 c8 97 3e 7f 89 fc 11 7d 1c a5 fd 99 16 03 |....>....}......| +00000290 03 00 5e 00 00 00 00 00 00 00 04 64 60 91 c0 fd |..^........d`...| +000002a0 3a 96 5a ac 5a 13 a9 9a 41 eb a0 6d 51 98 ee a8 |:.Z.Z...A..mQ...| +000002b0 4d ee 90 c9 3e a5 15 ac f3 6a c8 56 f3 20 c3 10 |M...>....j.V. ..| +000002c0 e3 3a d1 ea b0 7d a7 21 ae 2c b1 fa 5c b8 c1 fa |.:...}.!.,..\...| +000002d0 d7 97 6e ea fd 09 53 46 db aa e4 39 31 00 c2 bb |..n...SF...91...| +000002e0 ad 36 10 cd e9 cb 46 31 7b 66 ee ce 0c a8 f9 c2 |.6....F1{f......| +000002f0 0a 16 03 03 00 a0 00 00 00 00 00 00 00 05 6d a0 |..............m.| +00000300 03 60 12 bb 06 89 0c 03 ad f7 36 f3 5c e4 c1 65 |.`........6.\..e| +00000310 b2 26 c9 f5 87 85 f9 8f 2d 05 43 35 32 d7 0a a0 |.&......-.C52...| +00000320 e5 16 7a 94 62 15 ed cc 8e 9f e3 10 8d e7 83 a2 |..z.b...........| +00000330 ea e4 07 49 c9 df 1d 2b 6f b8 0f 67 31 22 44 9b |...I...+o..g1"D.| +00000340 65 77 99 78 f9 3e 14 67 3a 90 e5 5a c2 b5 1b ee |ew.x.>.g:..Z....| +00000350 db 20 73 8d 85 22 4d 79 6e e9 17 d0 b1 03 58 f3 |. s.."Myn.....X.| +00000360 cf 1b f5 03 9a 75 1f 7a 3b 49 ee 67 04 da c4 fc |.....u.z;I.g....| +00000370 7a 62 a9 ff 26 4f 71 b2 7e e9 c7 78 96 74 1e 63 |zb..&Oq.~..x.t.c| +00000380 eb 2b 2f 18 1f 19 cf 1e 89 73 39 9e f6 02 3d 31 |.+/......s9...=1| +00000390 50 65 1f 80 19 26 14 03 03 00 19 00 00 00 00 00 |Pe...&..........| +000003a0 00 00 06 82 62 df fd 51 9e be 21 0b 22 b6 c1 6d |....b..Q..!."..m| +000003b0 5c 90 ea c5 16 03 03 00 28 00 00 00 00 00 00 00 |\.......(.......| +000003c0 00 d6 5f a7 05 2b 99 cc 7d fb d7 38 5e e3 31 a7 |.._..+..}..8^.1.| +000003d0 c9 1c bd 7b c7 89 d0 e5 b5 93 78 d1 63 57 d2 76 |...{......x.cW.v| +000003e0 38 |8| +>>> Flow 10 (server to client) +00000000 14 03 03 00 19 b7 93 18 5b 36 18 ce 9d 68 22 e1 |........[6...h".| +00000010 d0 06 aa e5 87 f8 49 bc 38 d7 b9 38 85 97 16 03 |......I.8..8....| +00000020 03 00 28 24 71 bf 67 14 d6 5e 29 1b de e6 f4 e0 |..($q.g..^).....| +00000030 33 76 dc 66 c6 95 c0 3a 15 49 99 09 2f cf 6b 6b |3v.f...:.I../.kk| +00000040 a1 8f 1a e4 af 8d 1e 7f 02 b1 87 17 03 03 00 21 |...............!| +00000050 24 71 bf 67 14 d6 5e 2a 61 7b 98 dd e8 52 b0 1e |$q.g..^*a{...R..| +00000060 28 46 28 de e2 22 65 6c 66 85 3a 1d bb 9e 76 a2 |(F(.."elf.:...v.| +00000070 55 16 03 03 00 1c 24 71 bf 67 14 d6 5e 2b bb 84 |U.....$q.g..^+..| +00000080 6d f0 1c d0 46 89 bb b2 09 96 dd 95 53 bf ac d7 |m...F.......S...| +00000090 80 f1 |..| +>>> Flow 11 (client to server) +00000000 16 03 03 00 a9 00 00 00 00 00 00 00 01 61 12 ee |.............a..| +00000010 0a f2 5e e2 3d 3d 36 4c 14 10 20 aa 4d 8a 91 e4 |..^.==6L.. .M...| +00000020 c2 b0 63 68 9e f5 71 b7 a4 ee 75 27 20 8c 2e 21 |..ch..q...u' ..!| +00000030 f5 57 3d e9 9a 05 da 7b a5 af 6a 17 10 8b eb 25 |.W=....{..j....%| +00000040 8a 79 75 07 dc fe f5 7f a5 e2 63 31 ee 55 ba c0 |.yu.......c1.U..| +00000050 e6 3d de 03 36 2b 64 19 b1 1a b8 80 09 25 8c dd |.=..6+d......%..| +00000060 dd 59 c7 1d e7 40 20 ae ca a9 b5 14 a7 57 f0 62 |.Y...@ ......W.b| +00000070 71 88 a3 2c fc a4 50 dc 8b 85 22 20 38 c5 74 ea |q..,..P..." 8.t.| +00000080 ac 33 1d a3 c5 5c cc 10 62 fd c5 70 22 fa e3 73 |.3...\..b..p"..s| +00000090 f3 bf 24 14 0d cb 7c 25 e4 74 6c fe c0 70 5e a0 |..$...|%.tl..p^.| +000000a0 63 a7 e5 f2 6e d8 71 bd 7d b9 f0 b6 0b 70 |c...n.q.}....p| +>>> Flow 12 (server to client) +00000000 16 03 03 00 89 24 71 bf 67 14 d6 5e 2c 55 62 31 |.....$q.g..^,Ub1| +00000010 5c a3 53 1a c3 2f 89 47 62 33 7e 24 cd ad a9 5b |\.S../.Gb3~$...[| +00000020 51 79 d8 08 08 ff 09 3c 41 c7 80 ed ec 5a 7a e4 |Qy.....<A....Zz.| +00000030 71 e1 17 91 5e c1 80 58 35 c7 27 ca 62 74 cc d8 |q...^..X5.'.bt..| +00000040 e8 35 86 97 bf 05 73 b9 3f ae 5b af 9a 14 88 4b |.5....s.?.[....K| +00000050 f9 6f a4 de 3d 45 c8 7b 0a b1 7a 81 3e 7c 02 b5 |.o..=E.{..z.>|..| +00000060 e9 43 a5 64 88 59 f6 55 20 d1 09 39 cd 01 46 0f |.C.d.Y.U ..9..F.| +00000070 a2 06 f3 2b 45 14 b2 57 21 2c 2f a0 e5 db 02 99 |...+E..W!,/.....| +00000080 e4 6b 1e 22 99 c9 ae 93 e4 67 89 d1 c6 6d 16 03 |.k.".....g...m..| +00000090 03 02 89 24 71 bf 67 14 d6 5e 2d ce 6a 42 6b ce |...$q.g..^-.jBk.| +000000a0 07 4e ff 40 39 4b 00 c8 14 4c 76 e0 4d 09 41 c3 |.N.@9K...Lv.M.A.| +000000b0 41 3a ca ac 28 06 01 80 e4 b8 73 a2 fc ea 8d 92 |A:..(.....s.....| +000000c0 44 0e 43 3e d8 cb 8a 0c a0 c1 5e 88 6d 6d 80 be |D.C>......^.mm..| +000000d0 9c 9f cc 20 7c fa 6f e4 1a a1 39 c2 a8 7d 04 85 |... |.o...9..}..| +000000e0 75 5d c4 d3 6f df d7 3a 9d 83 c3 74 aa 49 df 34 |u]..o..:...t.I.4| +000000f0 e0 41 ad a3 80 80 c3 29 44 b9 5f a1 7b 67 89 30 |.A.....)D._.{g.0| +00000100 04 b0 90 78 6b 82 fe ae 0c eb e1 5a 64 e2 6f de |...xk......Zd.o.| +00000110 de 12 db 4f 1f eb 1d a9 66 a1 62 11 ab 54 1f 5d |...O....f.b..T.]| +00000120 c2 ce 1e a8 b3 8b 29 08 76 13 a0 67 5b e6 1b 2c |......).v..g[..,| +00000130 bd 1b 42 80 a5 09 b0 03 28 df 77 6f a7 d5 2f 85 |..B.....(.wo../.| +00000140 2b b1 69 81 5c a0 16 16 1c eb b4 61 f1 f7 70 55 |+.i.\......a..pU| +00000150 ee 64 9d 8f 1a 0b af af 18 f5 da e6 32 ab b2 28 |.d..........2..(| +00000160 0d a0 ea b4 44 3d a9 f7 1a 84 c1 8f 30 09 41 13 |....D=......0.A.| +00000170 a3 34 79 a7 6f da 76 59 62 9f d6 82 0f 48 21 64 |.4y.o.vYb....H!d| +00000180 11 49 53 cd 3a 44 5a dc 8b 97 8a 84 d2 f9 12 77 |.IS.:DZ........w| +00000190 b3 5b b0 37 58 7a a3 5a 47 9d c7 e4 83 f5 0a 32 |.[.7Xz.ZG......2| +000001a0 10 39 aa d6 7c 8e 44 eb a9 fd 0f c0 6a 80 82 21 |.9..|.D.....j..!| +000001b0 30 d1 36 31 73 38 c5 bd 16 99 71 b5 49 8e 7f df |0.61s8....q.I...| +000001c0 f9 64 7f ff 16 3b 68 7c b5 7c 1f 41 19 36 dd ef |.d...;h|.|.A.6..| +000001d0 65 11 b9 91 c4 d4 40 eb 37 94 69 8b 3b 10 56 45 |e.....@.7.i.;.VE| +000001e0 ee 56 a8 a7 3d 94 17 5c fe f2 88 c7 fb 78 8e 51 |.V..=..\.....x.Q| +000001f0 53 a8 bc b3 88 ee 75 42 1d 41 b8 c5 34 d5 9e bc |S.....uB.A..4...| +00000200 b4 b7 1c 97 8b 83 d6 3d 97 4b 43 7a 40 3d 63 6e |.......=.KCz@=cn| +00000210 cf 57 9a d3 71 6d 54 fe 38 ec 6f d7 c3 aa 1c a8 |.W..qmT.8.o.....| +00000220 2b f6 34 96 cb 16 da 3e 2d 74 dd f6 1c 33 3c 4e |+.4....>-t...3<N| +00000230 25 d9 e3 c5 85 52 c3 ea 22 ea 86 16 84 31 05 a4 |%....R.."....1..| +00000240 7d 41 00 bd 4a b3 79 93 18 1c a1 e4 78 1c 90 49 |}A..J.y.....x..I| +00000250 b4 9f bc d3 2d d0 f9 46 da 13 7c f6 88 5e e1 b2 |....-..F..|..^..| +00000260 5c 41 12 bf 2f 1f b4 c3 13 8c 2f a6 83 c5 86 ba |\A../...../.....| +00000270 20 42 21 57 e1 78 82 0e 4b 55 32 c1 f2 6e 4c a2 | B!W.x..KU2..nL.| +00000280 a7 c7 63 b3 b5 30 49 9d 7a 51 5e 67 38 52 89 ee |..c..0I.zQ^g8R..| +00000290 51 16 34 5c f6 b1 04 30 7b f4 b0 f8 88 6c 9d bc |Q.4\...0{....l..| +000002a0 32 5d 8b 73 b0 df f6 a2 dd e7 62 94 d7 b7 68 92 |2].s......b...h.| +000002b0 d6 a6 6a b2 53 75 d8 a7 43 1f 1e a2 c0 4e 6a 84 |..j.Su..C....Nj.| +000002c0 e7 6d ae 81 82 dc 43 bd 8c 44 6a db ec 37 34 70 |.m....C..Dj..74p| +000002d0 a0 e3 39 a1 17 d2 b7 53 bc 06 0e 33 3f 91 b3 a6 |..9....S...3?...| +000002e0 0a d1 43 b0 94 54 bc b9 07 52 40 6e 49 99 ab 09 |..C..T...R@nI...| +000002f0 3f dc 5d 5f c9 33 59 03 3f cf 7b 47 54 2d 05 4b |?.]_.3Y.?.{GT-.K| +00000300 c2 e6 81 f5 2f 58 5d 84 ad 9d 72 cc 3b 09 70 50 |..../X]...r.;.pP| +00000310 75 f8 c8 b7 9a 3f b7 3e aa 6a 75 5d 16 03 03 00 |u....?.>.ju]....| +00000320 e5 24 71 bf 67 14 d6 5e 2e 0b f5 20 45 e5 51 07 |.$q.g..^... E.Q.| +00000330 98 f0 75 3c 5c f3 16 88 ba e7 76 fe 10 18 41 38 |..u<\.....v...A8| +00000340 d5 df 7f 8b d3 2e 1c 0a 4c 83 57 fc e5 63 35 68 |........L.W..c5h| +00000350 6e 23 5b c3 0c 9d f9 ab f8 3c 86 b6 ec 54 ec 52 |n#[......<...T.R| +00000360 a4 45 cf 7b 31 a7 04 ef 5b 0b b1 11 50 8c 95 25 |.E.{1...[...P..%| +00000370 9a 17 9b 4d 65 9c 0b d3 bb 0d 98 10 d9 34 52 7a |...Me........4Rz| +00000380 f8 1e 9e 78 cb 41 27 47 31 cb 25 42 90 e9 3c 02 |...x.A'G1.%B..<.| +00000390 49 17 01 5f 06 d2 f4 58 35 75 d5 9d 54 65 15 0d |I.._...X5u..Te..| +000003a0 02 7e 94 fd c8 ac b8 c4 97 1c 9a 1c 9a 23 d5 d3 |.~...........#..| +000003b0 44 c6 9a dd f9 b4 d1 48 e9 3d a0 5b d4 66 b3 d9 |D......H.=.[.f..| +000003c0 11 0c d5 6d 0e 06 9c 00 90 30 d7 97 06 dc 0e e2 |...m.....0......| +000003d0 59 51 7f b5 2e b8 f7 eb be 66 56 fa 9d a4 92 db |YQ.......fV.....| +000003e0 82 3a d9 fc bd da c5 23 f6 2c 7b 36 2f a8 57 8e |.:.....#.,{6/.W.| +000003f0 c6 0a 48 50 e3 f4 e7 07 95 48 9b 45 a9 ba cb e0 |..HP.....H.E....| +00000400 3e ee 10 f9 0e cc 16 03 03 00 46 24 71 bf 67 14 |>.........F$q.g.| +00000410 d6 5e 2f 97 87 ae b8 b4 fb f1 67 2b e7 0f f4 be |.^/.......g+....| +00000420 24 0a f8 4a c0 42 4b 40 d3 ea e7 e0 f7 2a 9b 80 |$..J.BK@.....*..| +00000430 bb 62 c0 2d d5 f8 52 19 49 d4 4c 45 1d c2 28 e7 |.b.-..R.I.LE..(.| +00000440 8f fd b2 47 0e 22 d1 e1 b1 33 c1 26 6a fd 3f 9f |...G."...3.&j.?.| +00000450 d8 |.| +>>> Flow 13 (client to server) +00000000 16 03 03 02 89 00 00 00 00 00 00 00 02 32 20 c7 |.............2 .| +00000010 66 2d 3f e5 9b f9 e0 1c 7c 1f 3e 21 d9 51 af 9a |f-?.....|.>!.Q..| +00000020 60 65 99 c7 3e 0b 48 f2 a3 8f eb ea 75 da af 60 |`e..>.H.....u..`| +00000030 2e 5b ac 7f 9f d1 1f 69 86 18 49 3b 18 a2 e5 c5 |.[.....i..I;....| +00000040 d0 c7 fe 3e c6 15 3d 5d 04 4d aa 7e 28 e3 20 d3 |...>..=].M.~(. .| +00000050 55 c2 ed 4f 61 5f cc f9 39 5f 7d 3a 0f f2 81 5d |U..Oa_..9_}:...]| +00000060 fd 4e 86 92 12 cd 2b b7 e6 46 49 b7 b8 5f 8f e5 |.N....+..FI.._..| +00000070 b7 5e 64 2f 13 33 65 1c c8 c4 38 bd 70 94 23 e9 |.^d/.3e...8.p.#.| +00000080 b6 57 81 c8 23 d1 57 85 91 c5 bc 5b 33 55 eb f5 |.W..#.W....[3U..| +00000090 2d b3 76 53 44 e2 e8 66 fe 42 de f8 6f 03 37 d4 |-.vSD..f.B..o.7.| +000000a0 a0 a4 75 7a 03 7f 00 92 eb 45 2f b8 5d 01 d3 4b |..uz.....E/.]..K| +000000b0 e7 ca 2f 5b 3b 20 67 dc 32 2a 4c 06 1b 03 97 c1 |../[; g.2*L.....| +000000c0 38 40 35 79 31 25 b0 fe d8 f3 b7 ee 6c ad 62 3e |8@5y1%......l.b>| +000000d0 60 d6 96 6a 10 2b 14 8a 9e 72 f4 c9 63 6a 63 14 |`..j.+...r..cjc.| +000000e0 d1 b0 e4 1f e9 3d 85 9d ed 11 3f 85 eb fa ca 46 |.....=....?....F| +000000f0 17 f8 45 d5 65 28 79 8d 63 8e d7 22 40 9f c7 25 |..E.e(y.c.."@..%| +00000100 ae e0 72 9f 60 70 95 59 99 25 41 1a e6 e9 45 cb |..r.`p.Y.%A...E.| +00000110 3d 5a 2e 2d 4d c2 3c f2 3a 01 61 1f 96 d7 78 1a |=Z.-M.<.:.a...x.| +00000120 cd 14 bd 87 75 23 10 7f 67 e4 8e fa 0a 9d 5d e9 |....u#..g.....].| +00000130 12 f8 c7 35 c1 37 4c a4 91 a1 a5 de 79 9a a7 9c |...5.7L.....y...| +00000140 ce d2 c9 72 a8 fa a3 27 24 8d 14 4e d7 11 f3 e9 |...r...'$..N....| +00000150 07 4d 6d 47 92 4d e2 75 9a 71 d0 1e dd 09 61 0e |.MmG.M.u.q....a.| +00000160 16 36 84 3a b1 dd 9b f8 09 dd 73 78 ed f7 29 4e |.6.:......sx..)N| +00000170 a6 29 b0 31 54 72 ac 4b 7a 49 13 ba 9b ef b6 8b |.).1Tr.KzI......| +00000180 48 dd a1 a7 9d 25 0e b7 37 42 5f 70 27 a7 59 40 |H....%..7B_p'.Y@| +00000190 fe 72 1a 23 3e 71 b7 56 ef ff 02 c0 c9 07 99 20 |.r.#>q.V....... | +000001a0 19 d2 9e 65 a5 5e f1 15 d3 ec 6e bb b1 c4 bf c0 |...e.^....n.....| +000001b0 f8 71 19 bc 77 30 93 72 33 eb 1b c0 62 07 5e ca |.q..w0.r3...b.^.| +000001c0 4a bf 89 5d 5d 44 23 fb 58 8e 71 b4 58 41 b9 97 |J..]]D#.X.q.XA..| +000001d0 8b da b6 a0 b6 40 54 46 01 b9 47 79 21 bc 7c f3 |.....@TF..Gy!.|.| +000001e0 4c 46 a3 92 ce d6 ec ac 3b 5d 6f 19 65 d1 b0 cd |LF......;]o.e...| +000001f0 19 cd 2e 9d 6e 7d d3 57 44 c2 dd c6 56 dd e6 2b |....n}.WD...V..+| +00000200 06 c6 f1 46 f1 ba ce e6 d9 c8 1e 03 5d b5 15 37 |...F........]..7| +00000210 9d 8a d2 01 e7 28 33 30 a2 2b a3 42 d1 05 2f e9 |.....(30.+.B../.| +00000220 7f 50 bf c8 7f 7b f8 c7 7e 12 3f 97 5e d5 1c 34 |.P...{..~.?.^..4| +00000230 eb bf 2e c2 f0 6b 36 4e 09 c9 73 0e bb 3a cd f8 |.....k6N..s..:..| +00000240 5f 2a 13 4d f2 92 b3 ae 4f dd 0e 82 a0 58 a9 be |_*.M....O....X..| +00000250 2f c1 20 5c 64 48 11 e3 66 18 22 4d ea aa 76 21 |/. \dH..f."M..v!| +00000260 07 ac 5a f2 14 38 a7 d8 9a 58 f8 92 62 77 3c 59 |..Z..8...X..bw<Y| +00000270 1a 31 4e 3f 56 55 2b 9f 87 96 9c 7e c5 f0 10 fa |.1N?VU+....~....| +00000280 90 a1 0b 9e e4 66 74 99 80 da 58 85 3d bd 16 03 |.....ft...X.=...| +00000290 03 00 5e 00 00 00 00 00 00 00 03 42 d9 1d 19 27 |..^........B...'| +000002a0 98 c0 29 9e bc 35 99 e9 e9 de f5 7c b7 2f ce a1 |..)..5.....|./..| +000002b0 48 fe a9 79 26 c3 f1 74 63 73 3b 8d b7 4c 47 11 |H..y&..tcs;..LG.| +000002c0 7c ea 6d 09 4c 1c 10 1d c9 b4 63 d4 5e c4 f1 34 ||.m.L.....c.^..4| +000002d0 94 63 1c 04 a1 5f d0 65 7c b6 dd 2b a3 1c 1b 5f |.c..._.e|..+..._| +000002e0 5c d6 dc 7f e7 df c4 75 ad df cc ae 71 47 64 cc |\......u....qGd.| +000002f0 96 16 03 03 00 a0 00 00 00 00 00 00 00 04 61 37 |..............a7| +00000300 a3 98 54 d1 7c 5d 14 b9 04 72 6e 02 ab 1a 15 2c |..T.|]...rn....,| +00000310 93 07 15 ab 56 b1 ac d5 75 75 2e 25 ae 5e 3f fa |....V...uu.%.^?.| +00000320 d0 20 ff 9d e0 ef fd 25 ed 4d 60 56 c7 33 07 d0 |. .....%.M`V.3..| +00000330 57 09 e4 12 bd aa f0 d2 cc de 0d 45 23 ab b6 67 |W..........E#..g| +00000340 ea d3 bc e1 4d 3a 75 9f 2d bb 53 b4 70 67 ce 63 |....M:u.-.S.pg.c| +00000350 83 29 fa 27 2b db ea a3 19 be 79 77 cd 75 fb bf |.).'+.....yw.u..| +00000360 c1 27 86 a6 a9 27 06 49 e1 77 13 0d e4 78 0c 07 |.'...'.I.w...x..| +00000370 d4 1c af 76 f4 7b 05 04 5f 0f ec 66 f9 03 3e 81 |...v.{.._..f..>.| +00000380 41 be 24 5f 43 2a 99 56 06 a9 d7 be ca 62 46 a2 |A.$_C*.V.....bF.| +00000390 ba e1 a6 8b 1b 0a 14 03 03 00 19 00 00 00 00 00 |................| +000003a0 00 00 05 f9 8f d4 80 bf ed b3 38 3a 12 d9 91 b6 |..........8:....| +000003b0 cf 87 1a 1b 16 03 03 00 28 00 00 00 00 00 00 00 |........(.......| +000003c0 00 fb 80 da 9a 59 82 9d d2 35 57 57 dd 76 a1 b1 |.....Y...5WW.v..| +000003d0 4a dc a5 cb f6 81 3f e3 4d cc 0e 7f 3a 96 85 f3 |J.....?.M...:...| +000003e0 ea |.| +>>> Flow 14 (server to client) +00000000 14 03 03 00 19 24 71 bf 67 14 d6 5e 30 cc 1c 3f |.....$q.g..^0..?| +00000010 3c 20 07 b3 c3 79 d0 6e fd 59 e6 0d 47 fd 16 03 |< ...y.n.Y..G...| +00000020 03 00 28 54 db a5 f7 3d b3 18 49 39 e5 59 93 bb |..(T...=..I9.Y..| +00000030 64 93 1c ed 46 d6 f8 89 94 45 ba 4a 9e 73 2e cb |d...F....E.J.s..| +00000040 03 18 e4 26 6d 33 e3 34 73 d6 fc 17 03 03 00 21 |...&m3.4s......!| +00000050 54 db a5 f7 3d b3 18 4a aa 45 38 3b 50 02 44 37 |T...=..J.E8;P.D7| +00000060 6a d1 3e f9 d3 3b 33 33 d5 84 2d 52 33 7d 68 84 |j.>..;33..-R3}h.| +00000070 ef |.| +>>> Flow 15 (client to server) +00000000 15 03 03 00 1a 00 00 00 00 00 00 00 01 55 5f 94 |.............U_.| +00000010 25 d0 89 86 cb 8f 33 6f b7 b6 35 ec 0f 6a 87 |%.....3o..5..j.| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwiceRejected b/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwiceRejected new file mode 100644 index 0000000..fe2fa88 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwiceRejected @@ -0,0 +1,255 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./| +00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........| +00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....| +00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............| +00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................| +00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................| +00000080 03 ff 01 00 01 00 00 12 00 00 |..........| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 51 0e b9 8f 73 |....Y...U..Q...s| +00000010 ec 20 17 90 80 3a 43 7a bc 19 19 f5 75 c3 76 a6 |. ...:Cz....u.v.| +00000020 53 53 4b 77 ce dd ca 4b 1b 1e ed 20 8d e5 a7 6f |SSKw...K... ...o| +00000030 53 e9 a4 06 4b 01 a6 08 a1 90 e5 da c9 e3 74 b0 |S...K.........t.| +00000040 87 1f 17 1a 68 d3 f7 ae 39 b8 3e 80 c0 2f 00 00 |....h...9.>../..| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 71 0b 00 02 6d 00 02 6a 00 02 67 30 82 02 |..q...m..j..g0..| +00000070 63 30 82 01 cc a0 03 02 01 02 02 09 00 a2 73 00 |c0............s.| +00000080 0c 81 00 cb f3 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....| +00000090 01 0b 05 00 30 2b 31 17 30 15 06 03 55 04 0a 13 |....0+1.0...U...| +000000a0 0e 47 6f 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 |.Google TESTING1| +000000b0 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo| +000000c0 74 30 1e 17 0d 31 35 30 31 30 31 30 30 30 30 30 |t0...15010100000| +000000d0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000| +000000e0 5a 30 26 31 17 30 15 06 03 55 04 0a 13 0e 47 6f |Z0&1.0...U....Go| +000000f0 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 0b 30 09 |ogle TESTING1.0.| +00000100 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...| +00000110 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0| +00000120 81 89 02 81 81 00 af 87 88 f6 20 1b 95 65 6c 14 |.......... ..el.| +00000130 ab 44 05 af 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f |.D..;E...m..cM..| +00000140 fe 6a 62 35 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 |.jb5..J..|..%^zd| +00000150 31 66 00 ba f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 |1f.......k.v.._A| +00000160 cb 6e 56 15 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 |.nV.....<.9!f=+.| +00000170 d1 bc db 1c c0 a7 da b7 ca ad ba da cb d5 21 50 |..............!P| +00000180 ec de 8d ab d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 |.....k.K......l.| +00000190 b1 44 84 bd 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef |.D..!..}..M.....| +000001a0 fa d6 09 47 f2 fb 02 03 01 00 01 a3 81 93 30 81 |...G..........0.| +000001b0 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........| +000001c0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.| +000001d0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......| +000001e0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.| +000001f0 06 03 55 1d 0e 04 12 04 10 12 50 8d 89 6f 1b d1 |..U.......P..o..| +00000200 dc 54 4d 6e cb 69 5e 06 f4 30 1b 06 03 55 1d 23 |.TMn.i^..0...U.#| +00000210 04 14 30 12 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea |..0....=..f..@..| +00000220 b4 03 78 48 1a 41 30 19 06 03 55 1d 11 04 12 30 |..xH.A0...U....0| +00000230 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan| +00000240 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........| +00000250 03 81 81 00 92 7c af 91 55 12 18 96 59 31 a6 48 |.....|..U...Y1.H| +00000260 40 d5 2d d5 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d |@.-........|..0}| +00000270 3c dc 76 da 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b |<.v.O=...-3$k.{.| +00000280 67 59 11 21 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 |gY.!...w...n.-.5| +00000290 fa 64 5f 22 3e 63 10 6b be ff 14 86 6d 0d f0 15 |.d_">c.k....m...| +000002a0 31 a8 14 38 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 |1..8.;..,...Qv..| +000002b0 4f dd db 9b 84 04 86 40 fa 51 dd ba b4 8d eb e3 |O......@.Q......| +000002c0 46 de 46 b9 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea |F.F.O.....A4....| +000002d0 b0 ab 39 18 16 03 03 00 cd 0c 00 00 c9 03 00 17 |..9.............| +000002e0 41 04 5e 2e 43 b7 c2 0f e8 4a 33 aa b8 d6 04 7f |A.^.C....J3.....| +000002f0 2b be a2 e3 6f fa 05 1a d1 64 a7 d1 ec 45 f9 16 |+...o....d...E..| +00000300 b7 75 ad f2 52 3e a3 60 67 f8 fb 87 a0 c0 d4 2f |.u..R>.`g....../| +00000310 f4 66 c9 dd 38 40 79 5b 16 75 0b 16 6a d8 e5 ad |.f..8@y[.u..j...| +00000320 63 f3 04 01 00 80 5e 89 b3 6b f4 a1 35 b3 27 be |c.....^..k..5.'.| +00000330 6a d4 39 42 7c ac e2 d4 9f a0 a0 a3 95 22 b5 09 |j.9B|........"..| +00000340 70 4a 0c 6f cf 7f 69 f9 7d 27 c4 0d e7 b8 9c 82 |pJ.o..i.}'......| +00000350 c9 0d 1d bb 5c 23 20 eb ca 09 ca 02 a0 56 27 10 |....\# ......V'.| +00000360 c5 d6 13 7d cd 05 64 cc 53 20 5d df ac 00 90 7f |...}..d.S ].....| +00000370 d7 cd f2 a1 07 9c 06 c2 e6 d1 94 60 d3 c6 97 a6 |...........`....| +00000380 3c e5 89 67 e7 cc b7 c1 ba 75 dc 17 2b 47 ce 23 |<..g.....u..+G.#| +00000390 a3 37 3b 3f 32 39 ae 4a 64 17 d2 64 d1 75 23 8a |.7;?29.Jd..d.u#.| +000003a0 e3 b4 fa 75 17 72 16 03 03 00 04 0e 00 00 00 |...u.r.........| +>>> Flow 3 (client to server) +00000000 16 03 03 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..| +00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.| +00000020 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.| +00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I| +00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 03 00 01 |..h.A.Vk.Z......| +00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 4f ef |.....(........O.| +00000060 08 7c a7 de 53 70 7e 78 fb 08 79 97 1f bd 33 92 |.|..Sp~x..y...3.| +00000070 c5 46 4d 64 32 bb 94 f0 07 ad 7d 00 86 9e |.FMd2.....}...| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 28 59 c3 19 1f ed |..........(Y....| +00000010 d1 1b 54 5b 66 81 47 29 9a 77 84 87 a0 bd c5 d4 |..T[f.G).w......| +00000020 f0 4e e2 11 d3 1d 26 dd 87 7a 55 11 48 37 7f 3a |.N....&..zU.H7.:| +00000030 2c fc 62 |,.b| +>>> Flow 5 (client to server) +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 02 12 57 |...............W| +00000010 9d 64 c5 47 13 95 13 7b 2b 3e e0 f7 ae 49 0f c7 |.d.G...{+>...I..| +00000020 0e 3a 67 |.:g| +>>> Flow 6 (server to client) +00000000 16 03 03 00 1c 59 c3 19 1f ed d1 1b 55 ac 23 dc |.....Y......U.#.| +00000010 0c 35 65 1e 7a 65 4f 47 13 46 a0 d0 d0 4d 0a 1f |.5e.zeOG.F...M..| +00000020 5c |\| +>>> Flow 7 (client to server) +00000000 16 03 03 00 a9 00 00 00 00 00 00 00 02 c0 05 0c |................| +00000010 76 0a 46 19 16 17 a6 75 af 11 bb 73 37 74 a4 26 |v.F....u...s7t.&| +00000020 d9 16 93 b8 19 5e 2f 17 52 d1 12 9e 36 90 4e c9 |.....^/.R...6.N.| +00000030 7a f9 89 75 3b d9 d4 e1 2e cf a0 5d 03 7d cc f6 |z..u;......].}..| +00000040 73 aa a9 52 c7 65 78 d0 89 6f b1 15 6e f9 9e 55 |s..R.ex..o..n..U| +00000050 42 9e 22 09 df 97 00 31 b8 73 57 1b 93 ff 0c e7 |B."....1.sW.....| +00000060 46 29 40 79 a7 c0 de b9 44 93 7b 4d 35 a0 35 65 |F)@y....D.{M5.5e| +00000070 6e 58 07 90 2b 11 49 26 10 f7 c7 32 f7 8e 6e a7 |nX..+.I&...2..n.| +00000080 9b 75 ba cb 4a ce f7 f0 f1 31 ca 04 a6 02 d0 62 |.u..J....1.....b| +00000090 da 9b 8b 27 8e 04 b8 4a 49 0d d6 31 10 93 30 37 |...'...JI..1..07| +000000a0 ad ea d7 c4 49 98 90 f3 a1 45 f4 69 2e 59 |....I....E.i.Y| +>>> Flow 8 (server to client) +00000000 16 03 03 00 89 59 c3 19 1f ed d1 1b 56 c8 38 86 |.....Y......V.8.| +00000010 22 b6 5f 55 cb 0c e1 40 e6 12 f2 71 d5 09 bc 47 |"._U...@...q...G| +00000020 ea 83 38 3a 58 f4 34 da ae 7f 64 fb 8c bc 71 64 |..8:X.4...d...qd| +00000030 1b aa 84 e4 3e c1 cc c4 a9 05 36 13 5a 9b 1e c0 |....>.....6.Z...| +00000040 44 cc 86 54 f0 75 b7 d0 aa b0 f0 3a b5 c7 f1 cc |D..T.u.....:....| +00000050 1f cd 8e 9e 9e bb 24 23 c3 05 0b a5 1d f3 0b 41 |......$#.......A| +00000060 41 19 89 1e ee 51 fc b3 e8 e2 6e a8 3f c4 8b ab |A....Q....n.?...| +00000070 cb af d9 a1 7e 1c db e7 6c f6 23 71 c6 31 db 40 |....~...l.#q.1.@| +00000080 a8 a7 08 fb 1a ff 8d 94 53 88 9a 11 73 6a 16 03 |........S...sj..| +00000090 03 02 89 59 c3 19 1f ed d1 1b 57 17 dd 9c b5 a5 |...Y......W.....| +000000a0 89 12 3a 14 61 34 e0 1d 0b 35 d6 3a 6c 09 93 2b |..:.a4...5.:l..+| +000000b0 6c 69 ee f4 f3 be fb 42 33 99 fd 9a e6 21 38 68 |li.....B3....!8h| +000000c0 a6 19 37 43 24 81 ba 35 12 fe ab ed 49 0b 03 54 |..7C$..5....I..T| +000000d0 11 a7 74 4d bb ba e7 b9 f3 ee 6a 4e 1a 84 2f 03 |..tM......jN../.| +000000e0 0c d1 28 21 49 84 f4 3c 5b 15 92 07 5c 6a 24 89 |..(!I..<[...\j$.| +000000f0 00 cf 78 31 76 23 0f 9d 45 3b 93 a5 68 ee 9c 73 |..x1v#..E;..h..s| +00000100 14 3f 08 30 37 40 4e 8b a4 02 03 3c 4b 52 74 99 |.?.07@N....<KRt.| +00000110 0e 9a ec 40 c6 74 16 ef c5 48 68 33 86 d7 06 57 |...@.t...Hh3...W| +00000120 bf 8a 6f 3f 41 fe 4d f2 37 0a 1b fd fb 66 55 bd |..o?A.M.7....fU.| +00000130 70 4d b0 8c 4f 78 24 eb 1f 8f 22 c7 aa 07 89 04 |pM..Ox$...".....| +00000140 6a b3 07 15 37 25 21 63 97 39 b1 c1 9b fa 81 5e |j...7%!c.9.....^| +00000150 69 c9 c7 4a 9c 5d b3 6a 41 d0 5e b9 f4 d5 5c a1 |i..J.].jA.^...\.| +00000160 8e 8a ad 58 6e 5c 4f 73 62 38 1c 5f 8d b1 67 63 |...Xn\Osb8._..gc| +00000170 49 da 4b 4e 83 54 34 8f 8d 12 de 4e 43 4d dc b9 |I.KN.T4....NCM..| +00000180 02 ab 08 59 db 0b 45 7e f5 b8 e2 33 f1 04 de 16 |...Y..E~...3....| +00000190 05 bf b4 2b 07 a1 11 e4 9e 48 f7 52 ab 20 89 04 |...+.....H.R. ..| +000001a0 a7 44 28 7a 12 6c 19 ab 2f 68 1a d9 26 ec 72 a0 |.D(z.l../h..&.r.| +000001b0 62 83 48 6f 4b 70 7d 74 3a 43 4f a6 38 37 fe 59 |b.HoKp}t:CO.87.Y| +000001c0 6e 72 5d 81 7d 2c c7 e1 6b 06 47 41 56 17 2c 25 |nr].},..k.GAV.,%| +000001d0 06 b1 7f f5 10 0a 31 a3 12 b1 5c 01 2f e0 a6 e4 |......1...\./...| +000001e0 fa ab d2 0b 02 77 ad ac f8 54 db 70 20 0a 1f 04 |.....w...T.p ...| +000001f0 86 a8 32 05 26 ee 7d e0 e9 03 19 cc 8f 67 f5 b6 |..2.&.}......g..| +00000200 97 fe 06 5e c1 d5 df 25 f5 39 70 64 57 a8 c9 84 |...^...%.9pdW...| +00000210 8f 0f 25 f8 c8 f9 17 70 e5 00 3c 4a 9f 4b c1 d9 |..%....p..<J.K..| +00000220 6e b8 1a e4 6d 85 a4 e2 42 44 71 ba 43 9b 03 70 |n...m...BDq.C..p| +00000230 14 ff 72 5e 5c 69 24 2e 52 0c 73 8b df 50 99 68 |..r^\i$.R.s..P.h| +00000240 57 81 c1 ed b6 33 fc 74 15 45 fd a2 c4 8c f8 95 |W....3.t.E......| +00000250 bf 8d 0e 92 91 42 72 77 03 ec c6 f6 9a 02 ca 7d |.....Brw.......}| +00000260 3c 87 72 eb 8d 30 3a 5c b4 03 4a 6d 2e 83 22 c5 |<.r..0:\..Jm..".| +00000270 e2 4a 95 83 7a 72 72 f2 2a 11 25 4a bd 04 16 ab |.J..zrr.*.%J....| +00000280 6a 48 44 2b 99 fb 6f 61 9a 14 4a 42 1e bf d1 82 |jHD+..oa..JB....| +00000290 db 62 5f ac 1e 6d 1d 1b 0d 4b 9d 8d 3a 84 94 b4 |.b_..m...K..:...| +000002a0 aa 08 5b 90 7f d2 46 b0 a7 40 f4 55 76 6b 0d 4c |..[...F..@.Uvk.L| +000002b0 8e e3 8c fd ed 33 7d 93 f8 d8 c3 db 26 2d db a1 |.....3}.....&-..| +000002c0 24 bc b0 fb 26 5f ec 13 5f 97 05 bb 5c 3c cc a3 |$...&_.._...\<..| +000002d0 c2 57 58 cd 2e 70 0c a7 77 c5 e5 e8 0c 42 f2 e0 |.WX..p..w....B..| +000002e0 1c 11 0f 62 4b 84 49 c2 b7 10 83 2e 16 1c 38 d4 |...bK.I.......8.| +000002f0 10 f7 ca 71 7a 87 c5 a3 66 d2 98 1e c8 f2 c0 37 |...qz...f......7| +00000300 0e 28 31 fe 8e 3e f4 03 74 6e 91 42 22 cb 5d 7f |.(1..>..tn.B".].| +00000310 d2 22 da 3c f2 a0 2d 09 a9 a5 2d 14 16 03 03 00 |.".<..-...-.....| +00000320 e5 59 c3 19 1f ed d1 1b 58 3f 19 93 55 cb 19 f8 |.Y......X?..U...| +00000330 02 1a 43 b3 b2 6c 4e 3e ee 99 b3 df fd 45 24 ac |..C..lN>.....E$.| +00000340 63 e7 45 cc a4 44 ca cf 3a e1 81 88 01 9a b3 64 |c.E..D..:......d| +00000350 fe 6b 36 57 9f 81 fc 40 8d ef 21 af 00 be 43 f7 |.k6W...@..!...C.| +00000360 a3 3b a3 fa f0 01 f2 b4 ab 8a d1 a8 14 58 1b 6f |.;...........X.o| +00000370 75 01 35 92 54 a7 a6 c1 99 1e 92 d8 87 53 7b 42 |u.5.T........S{B| +00000380 4a 76 96 5e e9 db bb 4e f1 d9 bb e6 d2 b0 34 10 |Jv.^...N......4.| +00000390 1b 4c d5 2c ca af 19 0d 3e 77 ee 77 0e 5f ff e2 |.L.,....>w.w._..| +000003a0 02 c5 4a f2 ec 0b 7d cf d1 e7 3c 72 d2 17 4d 6c |..J...}...<r..Ml| +000003b0 a7 ca 3a 1b 00 2b 69 17 e5 a9 82 69 49 c2 ff 8a |..:..+i....iI...| +000003c0 f1 e8 ab 1b c3 8d da f1 31 ba a6 f4 7c 3c 01 6f |........1...|<.o| +000003d0 ed a8 6f e2 4f a3 68 77 b7 54 b5 87 1b 5c 5c fb |..o.O.hw.T...\\.| +000003e0 83 bf 48 4d 36 43 d6 f7 0a 48 74 f3 44 9d 43 53 |..HM6C...Ht.D.CS| +000003f0 f8 54 1b 57 97 24 53 5a 93 e2 e9 33 f0 35 5f 0a |.T.W.$SZ...3.5_.| +00000400 0d 4c ce 92 4d c9 16 03 03 00 46 59 c3 19 1f ed |.L..M.....FY....| +00000410 d1 1b 59 80 50 fc 3a 56 e0 0b 06 b4 58 39 0c d8 |..Y.P.:V....X9..| +00000420 4b b1 11 7a bd cf 1c 78 41 62 ee 22 74 61 7d 61 |K..z...xAb."ta}a| +00000430 91 3d 0a 74 a4 b0 cd 25 70 19 a5 de d8 1b df 12 |.=.t...%p.......| +00000440 4e b8 71 db ac bc 48 ea 89 32 ec 27 69 02 0d 8b |N.q...H..2.'i...| +00000450 83 |.| +>>> Flow 9 (client to server) +00000000 16 03 03 02 89 00 00 00 00 00 00 00 03 be 8d 55 |...............U| +00000010 8a 5b 24 10 db e3 f2 11 28 0d 26 cc 1b bc 38 fa |.[$.....(.&...8.| +00000020 1c 8c f8 c9 64 55 ec 43 16 f7 ca af 12 a8 1c 09 |....dU.C........| +00000030 0d b0 47 bc 9f 19 02 91 ab 9d 33 b4 bc 45 f7 4d |..G.......3..E.M| +00000040 53 85 4a 91 7e d3 2d dc d6 02 6e 4a 34 51 99 db |S.J.~.-...nJ4Q..| +00000050 f2 a1 8d 34 60 6f 15 6a f9 4d 7a 03 0b dc f7 c1 |...4`o.j.Mz.....| +00000060 99 c2 2c b8 4c a1 63 ce a2 fb 33 0d d6 dd d4 0a |..,.L.c...3.....| +00000070 88 0c 1d 5c ea 06 00 33 3a 06 6e 3d 63 b4 d5 0c |...\...3:.n=c...| +00000080 9b 69 f0 86 72 db 47 52 3d 61 0b 66 57 8d 7b 67 |.i..r.GR=a.fW.{g| +00000090 1e 42 aa b8 ca e6 d3 07 56 cf f5 09 14 25 a2 1d |.B......V....%..| +000000a0 3b 3e dd 0c 41 ac 66 05 3b db 59 85 9d e2 9f 8b |;>..A.f.;.Y.....| +000000b0 21 c0 9a 3b 0b 8e 5b 4b af ac 73 87 d3 b4 34 b7 |!..;..[K..s...4.| +000000c0 2e 26 b0 5d 10 3a 2e 00 cc ac 40 b5 72 40 69 fa |.&.].:....@.r@i.| +000000d0 11 04 b6 37 38 84 59 76 29 08 f0 0f 0f 79 40 7c |...78.Yv)....y@|| +000000e0 e4 08 15 b7 58 cd 6c f4 d6 77 d6 f8 cb 1d ca 5c |....X.l..w.....\| +000000f0 41 d7 f8 64 63 14 a5 a5 3a 13 ce 55 b4 0a d9 b5 |A..dc...:..U....| +00000100 34 f9 5e 69 f2 9a 62 88 b9 69 2f 93 08 2c 55 c4 |4.^i..b..i/..,U.| +00000110 5d 0d cb 92 ac 2c 30 27 83 11 68 9f 74 35 5d 3a |]....,0'..h.t5]:| +00000120 96 4c 57 91 95 a8 e7 03 fa b7 ae 8b 94 e3 39 38 |.LW...........98| +00000130 6d e1 ad b1 f7 26 2c 90 d4 3c eb a5 5e df e4 29 |m....&,..<..^..)| +00000140 39 ff ba d2 04 f4 b4 9c fa c2 da 34 bc 04 32 07 |9..........4..2.| +00000150 db 52 38 fd 92 89 4c e9 50 13 e5 90 e7 f1 88 5e |.R8...L.P......^| +00000160 c1 7a 9b fa 6e 1f 99 ce 52 77 0c 03 d8 a6 5d 64 |.z..n...Rw....]d| +00000170 ab 58 82 93 10 a1 4f 35 ea a3 6d af a9 64 17 3d |.X....O5..m..d.=| +00000180 fc a8 d8 9e 7e d7 44 af 2a c1 d6 a8 4d 78 b3 0b |....~.D.*...Mx..| +00000190 d1 0b 3d 54 e2 c8 df 84 61 cb 92 1a d8 ce 23 a3 |..=T....a.....#.| +000001a0 68 f7 af 40 53 09 f0 cc 00 7d 39 83 2c 6d f4 44 |h..@S....}9.,m.D| +000001b0 d6 95 59 06 0a ef 9c 74 39 b3 70 cb 0a 0c 13 cd |..Y....t9.p.....| +000001c0 ec 1f bf 75 93 01 1a 35 68 75 8b 80 15 80 7d a9 |...u...5hu....}.| +000001d0 d0 25 9a 52 bc 02 bf 71 eb 60 76 2a 74 90 c8 16 |.%.R...q.`v*t...| +000001e0 80 03 c2 a8 0c be 94 7c 12 b0 ee 45 3a 38 09 5a |.......|...E:8.Z| +000001f0 bf 8b ca 78 f3 9e 79 8a 9f 65 57 84 f8 33 79 2a |...x..y..eW..3y*| +00000200 f8 8c e0 c8 4b 9e 12 19 b1 3f ba cf 9d db 48 13 |....K....?....H.| +00000210 b4 b0 53 0e 7a 6b 1d 21 13 45 37 8d 90 75 88 f9 |..S.zk.!.E7..u..| +00000220 b5 9d 41 d0 ee 95 5f 6a e5 96 b6 48 ce 3b 43 20 |..A..._j...H.;C | +00000230 47 15 db eb ba af 6d bf 38 26 e7 ad 86 ba 1e 91 |G.....m.8&......| +00000240 be 8b df ba 5c 30 6e 3c 13 6a 96 68 13 24 bf 06 |....\0n<.j.h.$..| +00000250 f1 d2 b0 05 8f 8e 21 7f 6a 09 5f b8 be 0b c5 5f |......!.j._...._| +00000260 67 60 94 ec 78 65 6f 70 94 9b 15 82 07 f4 88 fb |g`..xeop........| +00000270 a2 94 68 f7 57 0a 9c ec ab 3f 8f d5 83 ec 6a 24 |..h.W....?....j$| +00000280 6f 88 4f 22 7f a1 82 cb ef ec 4c 33 b9 c1 16 03 |o.O"......L3....| +00000290 03 00 5e 00 00 00 00 00 00 00 04 34 f9 69 a5 83 |..^........4.i..| +000002a0 c5 86 34 51 f0 07 5b 44 51 36 c1 0d f7 71 c7 1b |..4Q..[DQ6...q..| +000002b0 70 27 aa 35 cd c7 10 76 fd 96 27 dc bc 6f 39 ff |p'.5...v..'..o9.| +000002c0 f1 a7 de e3 c5 21 70 e9 70 b1 52 d2 f0 be c0 72 |.....!p.p.R....r| +000002d0 e5 aa 2b 1a 1d a8 8f 10 37 b5 2f c7 b9 32 c8 3c |..+.....7./..2.<| +000002e0 7c c8 11 a5 dc aa 84 12 57 f1 ff 3b f9 04 a4 29 ||.......W..;...)| +000002f0 24 16 03 03 00 a0 00 00 00 00 00 00 00 05 1a 86 |$...............| +00000300 c7 35 6f 23 c5 38 85 85 0e 31 df 33 1a 42 6e f8 |.5o#.8...1.3.Bn.| +00000310 c3 f7 81 29 aa 03 85 8c 5a 8a e1 9b 1c d3 6f 7d |...)....Z.....o}| +00000320 36 41 45 30 06 2b dd 19 dc 22 9e 9e d4 bc 0e 51 |6AE0.+...".....Q| +00000330 65 59 e9 7e 1b a1 d1 54 4b 3c 9a 41 de b9 43 98 |eY.~...TK<.A..C.| +00000340 a5 ef 7a b8 77 69 f7 a5 80 02 d6 46 73 96 89 46 |..z.wi.....Fs..F| +00000350 43 3a d7 ae 21 64 db 05 b5 7d fc 83 a3 75 ba ad |C:..!d...}...u..| +00000360 0d d2 d6 9b 51 3b cb 37 85 46 92 b5 57 eb 2c dc |....Q;.7.F..W.,.| +00000370 b2 8f e2 c0 7f 29 bf 5e bd f0 26 dd 31 e4 31 af |.....).^..&.1.1.| +00000380 09 51 e4 26 09 56 a2 f4 5d fc c5 cb c8 da 51 ee |.Q.&.V..].....Q.| +00000390 35 2e bb 3e ee bb 14 03 03 00 19 00 00 00 00 00 |5..>............| +000003a0 00 00 06 b5 3d 07 af c9 3f ad f0 25 b4 5e b9 0f |....=...?..%.^..| +000003b0 fa f0 16 48 16 03 03 00 28 00 00 00 00 00 00 00 |...H....(.......| +000003c0 00 43 54 67 b4 f1 0e 1d 9d 7f ab f7 4c b6 77 3f |.CTg........L.w?| +000003d0 d0 17 da 6a 61 75 a8 c8 42 47 fb 2a f7 22 85 02 |...jau..BG.*."..| +000003e0 b0 |.| +>>> Flow 10 (server to client) +00000000 14 03 03 00 19 59 c3 19 1f ed d1 1b 5a 9d 51 67 |.....Y......Z.Qg| +00000010 ff ed 61 fd 01 85 c2 46 f1 26 e1 08 c3 5b 16 03 |..a....F.&...[..| +00000020 03 00 28 02 08 83 98 20 78 eb a5 8e f5 d3 31 b6 |..(.... x.....1.| +00000030 6d 4b 3a 9c cd 76 30 ca 92 4b 6c 17 2c d8 c5 d5 |mK:..v0..Kl.,...| +00000040 7d 59 76 f8 ff 0c 8f f4 f6 fb 81 17 03 03 00 21 |}Yv............!| +00000050 02 08 83 98 20 78 eb a6 9b c6 07 33 3b 43 e4 5b |.... x.....3;C.[| +00000060 c6 d4 31 6e 2b 5b 4a 65 c2 0a df 27 02 a2 3e 3b |..1n+[Je...'..>;| +00000070 04 16 03 03 00 1c 02 08 83 98 20 78 eb a7 43 45 |.......... x..CE| +00000080 df 9b 74 94 81 17 21 b1 7d d5 c0 7a 2b cc 38 a1 |..t...!.}..z+.8.| +00000090 30 1d |0.| +>>> Flow 11 (client to server) +00000000 15 03 03 00 1a 00 00 00 00 00 00 00 01 d6 2b 5a |..............+Z| +00000010 7d c9 ba d3 94 cc 45 26 1c 1e 1e 70 39 6c 4e 15 |}.....E&...p9lN.| +00000020 03 03 00 1a 00 00 00 00 00 00 00 02 fd 76 21 e8 |.............v!.| +00000030 b5 16 14 43 36 9f 61 14 6d 40 76 e3 14 11 |...C6.a.m@v...| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiationRejected b/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiationRejected new file mode 100644 index 0000000..90adc18 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiationRejected @@ -0,0 +1,97 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 22 c0 2f |............."./| +00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........| +00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....| +00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............| +00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................| +00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................| +00000080 03 ff 01 00 01 00 00 12 00 00 |..........| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 b1 7d c5 82 a4 |....Y...U...}...| +00000010 f7 1d 3a b9 c0 da 13 7c 2f 75 22 a4 5f 2e 58 2a |..:....|/u"._.X*| +00000020 39 eb 18 7c bb 0d 98 ba 51 2e 4a 20 41 40 2f 53 |9..|....Q.J A@/S| +00000030 bc 16 e0 a4 44 07 f0 5e 8f 43 a3 69 87 0b 94 dd |....D..^.C.i....| +00000040 60 a0 20 d0 25 e1 a1 a0 b8 0d d8 00 c0 2f 00 00 |`. .%......../..| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 71 0b 00 02 6d 00 02 6a 00 02 67 30 82 02 |..q...m..j..g0..| +00000070 63 30 82 01 cc a0 03 02 01 02 02 09 00 a2 73 00 |c0............s.| +00000080 0c 81 00 cb f3 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....| +00000090 01 0b 05 00 30 2b 31 17 30 15 06 03 55 04 0a 13 |....0+1.0...U...| +000000a0 0e 47 6f 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 |.Google TESTING1| +000000b0 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo| +000000c0 74 30 1e 17 0d 31 35 30 31 30 31 30 30 30 30 30 |t0...15010100000| +000000d0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000| +000000e0 5a 30 26 31 17 30 15 06 03 55 04 0a 13 0e 47 6f |Z0&1.0...U....Go| +000000f0 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 0b 30 09 |ogle TESTING1.0.| +00000100 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...| +00000110 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0| +00000120 81 89 02 81 81 00 af 87 88 f6 20 1b 95 65 6c 14 |.......... ..el.| +00000130 ab 44 05 af 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f |.D..;E...m..cM..| +00000140 fe 6a 62 35 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 |.jb5..J..|..%^zd| +00000150 31 66 00 ba f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 |1f.......k.v.._A| +00000160 cb 6e 56 15 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 |.nV.....<.9!f=+.| +00000170 d1 bc db 1c c0 a7 da b7 ca ad ba da cb d5 21 50 |..............!P| +00000180 ec de 8d ab d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 |.....k.K......l.| +00000190 b1 44 84 bd 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef |.D..!..}..M.....| +000001a0 fa d6 09 47 f2 fb 02 03 01 00 01 a3 81 93 30 81 |...G..........0.| +000001b0 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........| +000001c0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.| +000001d0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......| +000001e0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.| +000001f0 06 03 55 1d 0e 04 12 04 10 12 50 8d 89 6f 1b d1 |..U.......P..o..| +00000200 dc 54 4d 6e cb 69 5e 06 f4 30 1b 06 03 55 1d 23 |.TMn.i^..0...U.#| +00000210 04 14 30 12 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea |..0....=..f..@..| +00000220 b4 03 78 48 1a 41 30 19 06 03 55 1d 11 04 12 30 |..xH.A0...U....0| +00000230 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan| +00000240 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........| +00000250 03 81 81 00 92 7c af 91 55 12 18 96 59 31 a6 48 |.....|..U...Y1.H| +00000260 40 d5 2d d5 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d |@.-........|..0}| +00000270 3c dc 76 da 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b |<.v.O=...-3$k.{.| +00000280 67 59 11 21 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 |gY.!...w...n.-.5| +00000290 fa 64 5f 22 3e 63 10 6b be ff 14 86 6d 0d f0 15 |.d_">c.k....m...| +000002a0 31 a8 14 38 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 |1..8.;..,...Qv..| +000002b0 4f dd db 9b 84 04 86 40 fa 51 dd ba b4 8d eb e3 |O......@.Q......| +000002c0 46 de 46 b9 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea |F.F.O.....A4....| +000002d0 b0 ab 39 18 16 03 03 00 cd 0c 00 00 c9 03 00 17 |..9.............| +000002e0 41 04 62 2a a7 2d 1f 7a 8d 7e 8a 9e 84 db df e2 |A.b*.-.z.~......| +000002f0 7c 35 d8 a1 9f ec 23 ef c7 c2 9a c5 45 02 6f eb ||5....#.....E.o.| +00000300 24 ed 77 e1 ca fe 9a be 06 1e ea 30 5a e7 13 00 |$.w........0Z...| +00000310 47 52 a4 a2 d8 ee 9d 4e 87 f5 48 83 6f 5d 8e 02 |GR.....N..H.o]..| +00000320 ff f5 04 01 00 80 19 f6 63 a1 47 d1 cf 4d 28 73 |........c.G..M(s| +00000330 4e 31 03 78 b5 17 ba 53 64 d0 b8 3f 04 77 9d 6b |N1.x...Sd..?.w.k| +00000340 85 d0 d4 1e 02 90 b9 ab 10 dc d7 b1 79 1b 12 80 |............y...| +00000350 e1 5a 4b 69 80 2d 2a 37 4c fd 72 a9 c3 8e 2a 1f |.ZKi.-*7L.r...*.| +00000360 1a 3f 74 49 c6 49 ce 2f 02 58 3f 68 f0 f6 b5 8a |.?tI.I./.X?h....| +00000370 16 11 8b 63 15 6a f2 91 f1 74 a8 f0 6d dc 91 0a |...c.j...t..m...| +00000380 b4 e2 4e 10 14 1d b9 da 05 29 bf 31 30 ee 7d a5 |..N......).10.}.| +00000390 75 4e da ff db 43 04 a7 55 4b dd 93 4c 5f 32 be |uN...C..UK..L_2.| +000003a0 e9 23 c9 a1 23 86 16 03 03 00 04 0e 00 00 00 |.#..#..........| +>>> Flow 3 (client to server) +00000000 16 03 03 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..| +00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.| +00000020 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.| +00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I| +00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 03 00 01 |..h.A.Vk.Z......| +00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 d4 cb |.....(..........| +00000060 e2 c0 1e fe cb b0 d6 fe da 7c 8f 8c b2 2f f7 c1 |.........|.../..| +00000070 3d e9 52 6e 70 c1 13 13 87 ff 12 85 6c 2c |=.Rnp.......l,| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 28 0a 86 ff b2 73 |..........(....s| +00000010 35 40 a1 89 9f 21 1f 0b 2f 79 50 70 eb 74 e1 2f |5@...!../yPp.t./| +00000020 4d bc 5c 3c 85 0b 60 cc 73 36 e4 08 01 0a 4c 75 |M.\<..`.s6....Lu| +00000030 0f a2 9c |...| +>>> Flow 5 (client to server) +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 c9 78 b7 |..............x.| +00000010 07 d1 a9 95 fc b4 aa 57 16 77 86 fb c7 a9 c6 12 |.......W.w......| +00000020 bc bd 09 |...| +>>> Flow 6 (server to client) +00000000 16 03 03 00 1c 0a 86 ff b2 73 35 40 a2 4d b1 9b |.........s5@.M..| +00000010 eb 51 76 71 6b b8 88 fe 21 60 bb 8b 2a cc e3 3e |.Qvqk...!`..*..>| +00000020 d5 |.| +>>> Flow 7 (client to server) +00000000 15 03 03 00 1a 00 00 00 00 00 00 00 02 0e da c6 |................| +00000010 01 09 cc 0f bb 7d de c9 41 8d 30 b5 d5 b7 f2 15 |.....}..A.0.....| +00000020 03 03 00 1a 00 00 00 00 00 00 00 03 a7 0e 24 98 |..............$.| +00000030 32 62 1b a9 98 17 b6 b3 71 af 88 7a a3 6b |2b......q..z.k| diff --git a/libgo/go/crypto/tls/ticket.go b/libgo/go/crypto/tls/ticket.go index 7be50ce..3e7aa93 100644 --- a/libgo/go/crypto/tls/ticket.go +++ b/libgo/go/crypto/tls/ticket.go @@ -126,11 +126,7 @@ func (s *sessionState) unmarshal(data []byte) bool { data = data[certLen:] } - if len(data) > 0 { - return false - } - - return true + return len(data) == 0 } func (c *Conn) encryptTicket(state *sessionState) ([]byte, error) { diff --git a/libgo/go/crypto/tls/tls.go b/libgo/go/crypto/tls/tls.go index 4bedd76..8eef884 100644 --- a/libgo/go/crypto/tls/tls.go +++ b/libgo/go/crypto/tls/tls.go @@ -47,14 +47,13 @@ type listener struct { } // 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() +// The returned connection is of type *Conn. +func (l *listener) Accept() (net.Conn, error) { + c, err := l.Listener.Accept() if err != nil { - return + return nil, err } - c = Server(c, l.config) - return + return Server(c, l.config), nil } // NewListener creates a Listener which accepts connections from an inner @@ -136,9 +135,9 @@ func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (* // from the hostname we're connecting to. if config.ServerName == "" { // Make a copy to avoid polluting argument or default. - c := *config + c := config.clone() c.ServerName = hostname - config = &c + config = c } conn := Client(rawConn, config) @@ -171,10 +170,11 @@ 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. +// LoadX509KeyPair reads and parses a public/private key pair from a pair +// of files. The files must contain PEM encoded data. The certificate file +// may contain intermediate certificates following the leaf certificate to +// form a certificate chain. 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 { @@ -210,12 +210,12 @@ func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (Certificate, error) { 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)) + return fail(errors.New("tls: failed to find any PEM data in certificate input")) + } + if len(skippedBlockTypes) == 1 && strings.HasSuffix(skippedBlockTypes[0], "PRIVATE KEY") { + return fail(errors.New("tls: failed to find certificate PEM data in certificate input, but did find a private key; PEM inputs may have been switched")) } + return fail(fmt.Errorf("tls: failed to find \"CERTIFICATE\" PEM block in certificate input after skipping PEM blocks of the following types: %v", skippedBlockTypes)) } skippedBlockTypes = skippedBlockTypes[:0] @@ -224,12 +224,12 @@ func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (Certificate, error) { 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)) + return fail(errors.New("tls: failed to find any PEM data in key input")) } + if len(skippedBlockTypes) == 1 && skippedBlockTypes[0] == "CERTIFICATE" { + return fail(errors.New("tls: found a certificate rather than a key in the PEM for the private key")) + } + return fail(fmt.Errorf("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 @@ -254,22 +254,21 @@ func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (Certificate, error) { 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")) + return fail(errors.New("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")) + return fail(errors.New("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")) - + return fail(errors.New("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")) + return fail(errors.New("tls: private key does not match public key")) } default: - return fail(errors.New("crypto/tls: unknown public key algorithm")) + return fail(errors.New("tls: unknown public key algorithm")) } return cert, nil @@ -287,12 +286,12 @@ func parsePrivateKey(der []byte) (crypto.PrivateKey, error) { case *rsa.PrivateKey, *ecdsa.PrivateKey: return key, nil default: - return nil, errors.New("crypto/tls: found unknown private key type in PKCS#8 wrapping") + return nil, errors.New("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") + return nil, errors.New("tls: failed to parse private key") } diff --git a/libgo/go/crypto/tls/tls_test.go b/libgo/go/crypto/tls/tls_test.go index 5cc1427..48b46a0 100644 --- a/libgo/go/crypto/tls/tls_test.go +++ b/libgo/go/crypto/tls/tls_test.go @@ -6,13 +6,19 @@ package tls import ( "bytes" + "crypto/x509" "errors" "fmt" "internal/testenv" "io" + "math" + "math/rand" "net" + "os" + "reflect" "strings" "testing" + "testing/quick" "time" ) @@ -146,7 +152,7 @@ func TestX509MixedKeyPair(t *testing.T) { } } -func newLocalListener(t *testing.T) net.Listener { +func newLocalListener(t testing.TB) net.Listener { ln, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { ln, err = net.Listen("tcp6", "[::1]:0") @@ -188,18 +194,25 @@ func TestDialTimeout(t *testing.T) { t.Fatal("DialWithTimeout completed successfully") } - if !strings.Contains(err.Error(), "timed out") { - t.Errorf("resulting error not a timeout: %s", err) + if !isTimeoutError(err) { + t.Errorf("resulting error not a timeout: %v\nType %T: %#v", err, err, err) } } +func isTimeoutError(err error) bool { + if ne, ok := err.(net.Error); ok { + return ne.Timeout() + } + return false +} + // tests that Conn.Read returns (non-zero, io.EOF) instead of // (non-zero, nil) when a Close (alertCloseNotify) is sitting right // behind the application data in the buffer. func TestConnReadNonzeroAndEOF(t *testing.T) { // This test is racy: it assumes that after a write to a // localhost TCP connection, the peer TCP connection can - // immediately read it. Because it's racy, we skip this test + // immediately read it. Because it's racy, we skip this test // in short mode, and then retry it several times with an // increasing sleep in between our final write (via srv.Close // below) and the following read. @@ -228,8 +241,8 @@ func testConnReadNonzeroAndEOF(t *testing.T, delay time.Duration) error { srvCh <- nil return } - serverConfig := *testConfig - srv := Server(sconn, &serverConfig) + serverConfig := testConfig.clone() + srv := Server(sconn, serverConfig) if err := srv.Handshake(); err != nil { serr = fmt.Errorf("handshake: %v", err) srvCh <- nil @@ -238,8 +251,8 @@ func testConnReadNonzeroAndEOF(t *testing.T, delay time.Duration) error { srvCh <- srv }() - clientConfig := *testConfig - conn, err := Dial("tcp", ln.Addr().String(), &clientConfig) + clientConfig := testConfig.clone() + conn, err := Dial("tcp", ln.Addr().String(), clientConfig) if err != nil { t.Fatal(err) } @@ -282,8 +295,8 @@ func TestTLSUniqueMatches(t *testing.T) { if err != nil { t.Fatal(err) } - serverConfig := *testConfig - srv := Server(sconn, &serverConfig) + serverConfig := testConfig.clone() + srv := Server(sconn, serverConfig) if err := srv.Handshake(); err != nil { t.Fatal(err) } @@ -291,9 +304,9 @@ func TestTLSUniqueMatches(t *testing.T) { } }() - clientConfig := *testConfig + clientConfig := testConfig.clone() clientConfig.ClientSessionCache = NewLRUClientSessionCache(1) - conn, err := Dial("tcp", ln.Addr().String(), &clientConfig) + conn, err := Dial("tcp", ln.Addr().String(), clientConfig) if err != nil { t.Fatal(err) } @@ -302,7 +315,7 @@ func TestTLSUniqueMatches(t *testing.T) { } conn.Close() - conn, err = Dial("tcp", ln.Addr().String(), &clientConfig) + conn, err = Dial("tcp", ln.Addr().String(), clientConfig) if err != nil { t.Fatal(err) } @@ -381,8 +394,8 @@ func TestConnCloseBreakingWrite(t *testing.T) { srvCh <- nil return } - serverConfig := *testConfig - srv := Server(sconn, &serverConfig) + serverConfig := testConfig.clone() + srv := Server(sconn, serverConfig) if err := srv.Handshake(); err != nil { serr = fmt.Errorf("handshake: %v", err) srvCh <- nil @@ -401,8 +414,8 @@ func TestConnCloseBreakingWrite(t *testing.T) { Conn: cconn, } - clientConfig := *testConfig - tconn := Client(conn, &clientConfig) + clientConfig := testConfig.clone() + tconn := Client(conn, clientConfig) if err := tconn.Handshake(); err != nil { t.Fatal(err) } @@ -445,6 +458,58 @@ func TestConnCloseBreakingWrite(t *testing.T) { } } +func TestClone(t *testing.T) { + var c1 Config + v := reflect.ValueOf(&c1).Elem() + + rnd := rand.New(rand.NewSource(time.Now().Unix())) + typ := v.Type() + for i := 0; i < typ.NumField(); i++ { + f := v.Field(i) + if !f.CanSet() { + // unexported field; not cloned. + continue + } + + // testing/quick can't handle functions or interfaces. + fn := typ.Field(i).Name + switch fn { + case "Rand": + f.Set(reflect.ValueOf(io.Reader(os.Stdin))) + continue + case "Time", "GetCertificate": + // DeepEqual can't compare functions. + continue + case "Certificates": + f.Set(reflect.ValueOf([]Certificate{ + {Certificate: [][]byte{[]byte{'b'}}}, + })) + continue + case "NameToCertificate": + f.Set(reflect.ValueOf(map[string]*Certificate{"a": nil})) + continue + case "RootCAs", "ClientCAs": + f.Set(reflect.ValueOf(x509.NewCertPool())) + continue + case "ClientSessionCache": + f.Set(reflect.ValueOf(NewLRUClientSessionCache(10))) + continue + } + + q, ok := quick.Value(f.Type(), rnd) + if !ok { + t.Fatalf("quick.Value failed on field %s", fn) + } + f.Set(q) + } + + c2 := c1.clone() + + if !reflect.DeepEqual(&c1, c2) { + t.Errorf("clone failed to copy a field") + } +} + // changeImplConn is a net.Conn which can change its Write and Close // methods. type changeImplConn struct { @@ -466,3 +531,161 @@ func (w *changeImplConn) Close() error { } return w.Conn.Close() } + +func throughput(b *testing.B, totalBytes int64, dynamicRecordSizingDisabled bool) { + ln := newLocalListener(b) + defer ln.Close() + + N := b.N + + // Less than 64KB because Windows appears to use a TCP rwin < 64KB. + // See Issue #15899. + const bufsize = 32 << 10 + + go func() { + buf := make([]byte, bufsize) + for i := 0; i < N; i++ { + sconn, err := ln.Accept() + if err != nil { + // panic rather than synchronize to avoid benchmark overhead + // (cannot call b.Fatal in goroutine) + panic(fmt.Errorf("accept: %v", err)) + } + serverConfig := testConfig.clone() + serverConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled + srv := Server(sconn, serverConfig) + if err := srv.Handshake(); err != nil { + panic(fmt.Errorf("handshake: %v", err)) + } + if _, err := io.CopyBuffer(srv, srv, buf); err != nil { + panic(fmt.Errorf("copy buffer: %v", err)) + } + } + }() + + b.SetBytes(totalBytes) + clientConfig := testConfig.clone() + clientConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled + + buf := make([]byte, bufsize) + chunks := int(math.Ceil(float64(totalBytes) / float64(len(buf)))) + for i := 0; i < N; i++ { + conn, err := Dial("tcp", ln.Addr().String(), clientConfig) + if err != nil { + b.Fatal(err) + } + for j := 0; j < chunks; j++ { + _, err := conn.Write(buf) + if err != nil { + b.Fatal(err) + } + _, err = io.ReadFull(conn, buf) + if err != nil { + b.Fatal(err) + } + } + conn.Close() + } +} + +func BenchmarkThroughput(b *testing.B) { + for _, mode := range []string{"Max", "Dynamic"} { + for size := 1; size <= 64; size <<= 1 { + name := fmt.Sprintf("%sPacket/%dMB", mode, size) + b.Run(name, func(b *testing.B) { + throughput(b, int64(size<<20), mode == "Max") + }) + } + } +} + +type slowConn struct { + net.Conn + bps int +} + +func (c *slowConn) Write(p []byte) (int, error) { + if c.bps == 0 { + panic("too slow") + } + t0 := time.Now() + wrote := 0 + for wrote < len(p) { + time.Sleep(100 * time.Microsecond) + allowed := int(time.Since(t0).Seconds()*float64(c.bps)) / 8 + if allowed > len(p) { + allowed = len(p) + } + if wrote < allowed { + n, err := c.Conn.Write(p[wrote:allowed]) + wrote += n + if err != nil { + return wrote, err + } + } + } + return len(p), nil +} + +func latency(b *testing.B, bps int, dynamicRecordSizingDisabled bool) { + ln := newLocalListener(b) + defer ln.Close() + + N := b.N + + go func() { + for i := 0; i < N; i++ { + sconn, err := ln.Accept() + if err != nil { + // panic rather than synchronize to avoid benchmark overhead + // (cannot call b.Fatal in goroutine) + panic(fmt.Errorf("accept: %v", err)) + } + serverConfig := testConfig.clone() + serverConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled + srv := Server(&slowConn{sconn, bps}, serverConfig) + if err := srv.Handshake(); err != nil { + panic(fmt.Errorf("handshake: %v", err)) + } + io.Copy(srv, srv) + } + }() + + clientConfig := testConfig.clone() + clientConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled + + buf := make([]byte, 16384) + peek := make([]byte, 1) + + for i := 0; i < N; i++ { + conn, err := Dial("tcp", ln.Addr().String(), clientConfig) + if err != nil { + b.Fatal(err) + } + // make sure we're connected and previous connection has stopped + if _, err := conn.Write(buf[:1]); err != nil { + b.Fatal(err) + } + if _, err := io.ReadFull(conn, peek); err != nil { + b.Fatal(err) + } + if _, err := conn.Write(buf); err != nil { + b.Fatal(err) + } + if _, err = io.ReadFull(conn, peek); err != nil { + b.Fatal(err) + } + conn.Close() + } +} + +func BenchmarkLatency(b *testing.B) { + for _, mode := range []string{"Max", "Dynamic"} { + for _, kbps := range []int{200, 500, 1000, 2000, 5000} { + name := fmt.Sprintf("%sPacket/%dkbps", mode, kbps) + b.Run(name, func(b *testing.B) { + latency(b, kbps*1000, mode == "Max") + }) + } + } +} diff --git a/libgo/go/crypto/x509/cert_pool.go b/libgo/go/crypto/x509/cert_pool.go index 2362e84..59ab887 100644 --- a/libgo/go/crypto/x509/cert_pool.go +++ b/libgo/go/crypto/x509/cert_pool.go @@ -6,6 +6,8 @@ package x509 import ( "encoding/pem" + "errors" + "runtime" ) // CertPool is a set of certificates. @@ -18,12 +20,22 @@ type CertPool struct { // NewCertPool returns a new, empty CertPool. func NewCertPool() *CertPool { return &CertPool{ - make(map[string][]int), - make(map[string][]int), - nil, + bySubjectKeyId: make(map[string][]int), + byName: make(map[string][]int), } } +// SystemCertPool returns a copy of the system cert pool. +// +// Any mutations to the returned pool are not written to disk and do +// not affect any other pool. +func SystemCertPool() (*CertPool, error) { + if runtime.GOOS == "windows" { + return nil, errors.New("crypto/x509: system root pool is not available on Windows") + } + return loadSystemRoots() +} + // findVerifiedParents attempts to find certificates in s which have signed the // given certificate. If any candidates were rejected then errCert will be set // to one of them, arbitrarily, and err will contain the reason that it was @@ -107,10 +119,10 @@ func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) { // Subjects returns a list of the DER-encoded subjects of // all of the certificates in the pool. -func (s *CertPool) Subjects() (res [][]byte) { - res = make([][]byte, len(s.certs)) +func (s *CertPool) Subjects() [][]byte { + res := make([][]byte, len(s.certs)) for i, c := range s.certs { res[i] = c.RawSubject } - return + return res } diff --git a/libgo/go/crypto/x509/pem_decrypt.go b/libgo/go/crypto/x509/pem_decrypt.go index 49ceadb..0388d63 100644 --- a/libgo/go/crypto/x509/pem_decrypt.go +++ b/libgo/go/crypto/x509/pem_decrypt.go @@ -42,7 +42,7 @@ type rfc1423Algo struct { } // rfc1423Algos holds a slice of the possible ways to encrypt a PEM -// block. The ivSize numbers were taken from the OpenSSL source. +// block. The ivSize numbers were taken from the OpenSSL source. var rfc1423Algos = []rfc1423Algo{{ cipher: PEMCipherDES, name: "DES-CBC", diff --git a/libgo/go/crypto/x509/pkcs1.go b/libgo/go/crypto/x509/pkcs1.go index acebe35..df20a44 100644 --- a/libgo/go/crypto/x509/pkcs1.go +++ b/libgo/go/crypto/x509/pkcs1.go @@ -36,15 +36,14 @@ type pkcs1AdditionalRSAPrime struct { } // ParsePKCS1PrivateKey returns an RSA private key from its ASN.1 PKCS#1 DER encoded form. -func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err error) { +func ParsePKCS1PrivateKey(der []byte) (*rsa.PrivateKey, error) { var priv pkcs1PrivateKey rest, err := asn1.Unmarshal(der, &priv) if len(rest) > 0 { - err = asn1.SyntaxError{Msg: "trailing data"} - return + return nil, asn1.SyntaxError{Msg: "trailing data"} } if err != nil { - return + return nil, err } if priv.Version > 1 { @@ -55,7 +54,7 @@ func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err error) { return nil, errors.New("x509: private key contains zero or negative value") } - key = new(rsa.PrivateKey) + key := new(rsa.PrivateKey) key.PublicKey = rsa.PublicKey{ E: priv.E, N: priv.N, @@ -80,7 +79,7 @@ func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err error) { } key.Precompute() - return + return key, nil } // MarshalPKCS1PrivateKey converts a private key to ASN.1 DER encoded form. diff --git a/libgo/go/crypto/x509/pkcs8.go b/libgo/go/crypto/x509/pkcs8.go index ba19989..b304a3f 100644 --- a/libgo/go/crypto/x509/pkcs8.go +++ b/libgo/go/crypto/x509/pkcs8.go @@ -13,7 +13,7 @@ import ( // pkcs8 reflects an ASN.1, PKCS#8 PrivateKey. See // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-8/pkcs-8v1_2.asn -// and RFC5208. +// and RFC 5208. type pkcs8 struct { Version int Algo pkix.AlgorithmIdentifier @@ -21,8 +21,8 @@ type pkcs8 struct { // optional attributes omitted. } -// ParsePKCS8PrivateKey parses an unencrypted, PKCS#8 private key. See -// http://www.rsa.com/rsalabs/node.asp?id=2130 and RFC5208. +// ParsePKCS8PrivateKey parses an unencrypted, PKCS#8 private key. +// See RFC 5208. func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) { var privKey pkcs8 if _, err := asn1.Unmarshal(der, &privKey); err != nil { diff --git a/libgo/go/crypto/x509/pkix/pkix.go b/libgo/go/crypto/x509/pkix/pkix.go index 1b3e3c0..faad406 100644 --- a/libgo/go/crypto/x509/pkix/pkix.go +++ b/libgo/go/crypto/x509/pkix/pkix.go @@ -177,7 +177,7 @@ func (certList *CertificateList) HasExpired(now time.Time) bool { // 5280, section 5.1. type TBSCertificateList struct { Raw asn1.RawContent - Version int `asn1:"optional,default:1"` + Version int `asn1:"optional,default:0"` Signature AlgorithmIdentifier Issuer RDNSequence ThisUpdate time.Time diff --git a/libgo/go/crypto/x509/root.go b/libgo/go/crypto/x509/root.go index 8aae14e..787d955 100644 --- a/libgo/go/crypto/x509/root.go +++ b/libgo/go/crypto/x509/root.go @@ -7,11 +7,16 @@ package x509 import "sync" var ( - once sync.Once - systemRoots *CertPool + once sync.Once + systemRoots *CertPool + systemRootsErr error ) func systemRootsPool() *CertPool { once.Do(initSystemRoots) return systemRoots } + +func initSystemRoots() { + systemRoots, systemRootsErr = loadSystemRoots() +} diff --git a/libgo/go/crypto/x509/root_cgo_darwin.go b/libgo/go/crypto/x509/root_cgo_darwin.go index bf4a5cd..0e2fb35 100644 --- a/libgo/go/crypto/x509/root_cgo_darwin.go +++ b/libgo/go/crypto/x509/root_cgo_darwin.go @@ -21,59 +21,91 @@ package x509 // Note: The CFDataRef returned in pemRoots must be released (using CFRelease) after // we've consumed its content. int FetchPEMRoots(CFDataRef *pemRoots) { - if (pemRoots == NULL) { - return -1; - } + // Get certificates from all domains, not just System, this lets + // the user add CAs to their "login" keychain, and Admins to add + // to the "System" keychain + SecTrustSettingsDomain domains[] = { kSecTrustSettingsDomainSystem, + kSecTrustSettingsDomainAdmin, + kSecTrustSettingsDomainUser }; - CFArrayRef certs = NULL; - OSStatus err = SecTrustCopyAnchorCertificates(&certs); - if (err != noErr) { + int numDomains = sizeof(domains)/sizeof(SecTrustSettingsDomain); + if (pemRoots == NULL) { return -1; } CFMutableDataRef combinedData = CFDataCreateMutable(kCFAllocatorDefault, 0); - int i, ncerts = CFArrayGetCount(certs); - for (i = 0; i < ncerts; i++) { - CFDataRef data = NULL; - SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, i); - if (cert == NULL) { - continue; - } - - // Note: SecKeychainItemExport is deprecated as of 10.7 in favor of SecItemExport. - // Once we support weak imports via cgo we should prefer that, and fall back to this - // for older systems. - err = SecKeychainItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data); + for (int i = 0; i < numDomains; i++) { + CFArrayRef certs = NULL; + // Only get certificates from domain that are trusted + OSStatus err = SecTrustSettingsCopyCertificates(domains[i], &certs); if (err != noErr) { continue; } - if (data != NULL) { - CFDataAppendBytes(combinedData, CFDataGetBytePtr(data), CFDataGetLength(data)); - CFRelease(data); - } - } + int numCerts = CFArrayGetCount(certs); + for (int j = 0; j < numCerts; j++) { + CFDataRef data = NULL; + CFErrorRef errRef = NULL; + SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, j); + if (cert == NULL) { + continue; + } + // We only want to add Root CAs, so make sure Subject and Issuer Name match + CFDataRef subjectName = SecCertificateCopyNormalizedSubjectContent(cert, &errRef); + if (errRef != NULL) { + CFRelease(errRef); + continue; + } + CFDataRef issuerName = SecCertificateCopyNormalizedIssuerContent(cert, &errRef); + if (errRef != NULL) { + CFRelease(subjectName); + CFRelease(errRef); + continue; + } + Boolean equal = CFEqual(subjectName, issuerName); + CFRelease(subjectName); + CFRelease(issuerName); + if (!equal) { + continue; + } - CFRelease(certs); + // Note: SecKeychainItemExport is deprecated as of 10.7 in favor of SecItemExport. + // Once we support weak imports via cgo we should prefer that, and fall back to this + // for older systems. + err = SecKeychainItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data); + if (err != noErr) { + continue; + } + if (data != NULL) { + CFDataAppendBytes(combinedData, CFDataGetBytePtr(data), CFDataGetLength(data)); + CFRelease(data); + } + } + CFRelease(certs); + } *pemRoots = combinedData; return 0; } */ import "C" -import "unsafe" +import ( + "errors" + "unsafe" +) -func initSystemRoots() { +func loadSystemRoots() (*CertPool, error) { roots := NewCertPool() var data C.CFDataRef = nil err := C.FetchPEMRoots(&data) if err == -1 { - return + // TODO: better error message + return nil, errors.New("crypto/x509: failed to load darwin system roots with cgo") } defer C.CFRelease(C.CFTypeRef(data)) buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data))) roots.AppendCertsFromPEM(buf) - systemRoots = roots + return roots, nil } diff --git a/libgo/go/crypto/x509/root_darwin_arm_gen.go b/libgo/go/crypto/x509/root_darwin_arm_gen.go index 5817158..fc2488a 100644 --- a/libgo/go/crypto/x509/root_darwin_arm_gen.go +++ b/libgo/go/crypto/x509/root_darwin_arm_gen.go @@ -184,8 +184,9 @@ const header = ` package x509 -func initSystemRoots() { - systemRoots = NewCertPool() - systemRoots.AppendCertsFromPEM([]byte(systemRootsPEM)) +func loadSystemRoots() (*CertPool, error) { + p := NewCertPool() + p.AppendCertsFromPEM([]byte(systemRootsPEM)) + return p, nil } ` diff --git a/libgo/go/crypto/x509/root_darwin_armx.go b/libgo/go/crypto/x509/root_darwin_armx.go index 37675b4..ad1c53d 100644 --- a/libgo/go/crypto/x509/root_darwin_armx.go +++ b/libgo/go/crypto/x509/root_darwin_armx.go @@ -10,9 +10,10 @@ package x509 -func initSystemRoots() { - systemRoots = NewCertPool() - systemRoots.AppendCertsFromPEM([]byte(systemRootsPEM)) +func loadSystemRoots() (*CertPool, error) { + p := NewCertPool() + p.AppendCertsFromPEM([]byte(systemRootsPEM)) + return p, nil } const systemRootsPEM = ` diff --git a/libgo/go/crypto/x509/root_nocgo_darwin.go b/libgo/go/crypto/x509/root_nocgo_darwin.go index d00e257..2ac4666 100644 --- a/libgo/go/crypto/x509/root_nocgo_darwin.go +++ b/libgo/go/crypto/x509/root_nocgo_darwin.go @@ -6,6 +6,6 @@ package x509 -func initSystemRoots() { - systemRoots, _ = execSecurityRoots() +func loadSystemRoots() (*CertPool, error) { + return execSecurityRoots() } diff --git a/libgo/go/crypto/x509/root_plan9.go b/libgo/go/crypto/x509/root_plan9.go index 9965caa..ebeb7df 100644 --- a/libgo/go/crypto/x509/root_plan9.go +++ b/libgo/go/crypto/x509/root_plan9.go @@ -6,7 +6,10 @@ package x509 -import "io/ioutil" +import ( + "io/ioutil" + "os" +) // Possible certificate files; stop after finding one. var certFiles = []string{ @@ -17,17 +20,18 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate return nil, nil } -func initSystemRoots() { +func loadSystemRoots() (*CertPool, error) { roots := NewCertPool() + var bestErr error for _, file := range certFiles { data, err := ioutil.ReadFile(file) if err == nil { roots.AppendCertsFromPEM(data) - systemRoots = roots - return + return roots, nil + } + if bestErr == nil || (os.IsNotExist(bestErr) && !os.IsNotExist(err)) { + bestErr = err } } - - // All of the files failed to load. systemRoots will be nil which will - // trigger a specific error at verification time. + return nil, bestErr } diff --git a/libgo/go/crypto/x509/root_unix.go b/libgo/go/crypto/x509/root_unix.go index 9f06f9d..7bcb3d6 100644 --- a/libgo/go/crypto/x509/root_unix.go +++ b/libgo/go/crypto/x509/root_unix.go @@ -6,7 +6,10 @@ package x509 -import "io/ioutil" +import ( + "io/ioutil" + "os" +) // Possible directories with certificate files; stop after successfully // reading at least one file from a directory. @@ -19,20 +22,26 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate return nil, nil } -func initSystemRoots() { +func loadSystemRoots() (*CertPool, error) { roots := NewCertPool() + var firstErr error for _, file := range certFiles { data, err := ioutil.ReadFile(file) if err == nil { roots.AppendCertsFromPEM(data) - systemRoots = roots - return + return roots, nil + } + if firstErr == nil && !os.IsNotExist(err) { + firstErr = err } } for _, directory := range certDirectories { fis, err := ioutil.ReadDir(directory) if err != nil { + if firstErr == nil && !os.IsNotExist(err) { + firstErr = err + } continue } rootsAdded := false @@ -43,11 +52,9 @@ func initSystemRoots() { } } if rootsAdded { - systemRoots = roots - return + return roots, nil } } - // All of the files failed to load. systemRoots will be nil which will - // trigger a specific error at verification time. + return nil, firstErr } diff --git a/libgo/go/crypto/x509/root_windows.go b/libgo/go/crypto/x509/root_windows.go index 81018b7..392c869 100644 --- a/libgo/go/crypto/x509/root_windows.go +++ b/libgo/go/crypto/x509/root_windows.go @@ -179,7 +179,7 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate } // CertGetCertificateChain will traverse Windows's root stores - // in an attempt to build a verified certificate chain. Once + // in an attempt to build a verified certificate chain. Once // it has found a verified chain, it stops. MSDN docs on // CERT_CHAIN_CONTEXT: // @@ -225,5 +225,4 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate return chains, nil } -func initSystemRoots() { -} +func loadSystemRoots() (*CertPool, error) { return nil, nil } diff --git a/libgo/go/crypto/x509/sec1.go b/libgo/go/crypto/x509/sec1.go index 1424dea..33f376c 100644 --- a/libgo/go/crypto/x509/sec1.go +++ b/libgo/go/crypto/x509/sec1.go @@ -17,9 +17,9 @@ const ecPrivKeyVersion = 1 // ecPrivateKey reflects an ASN.1 Elliptic Curve Private Key Structure. // References: -// RFC5915 +// RFC 5915 // SEC1 - http://www.secg.org/sec1-v2.pdf -// Per RFC5915 the NamedCurveOID is marked as ASN.1 OPTIONAL, however in +// Per RFC 5915 the NamedCurveOID is marked as ASN.1 OPTIONAL, however in // most cases it is not. type ecPrivateKey struct { Version int @@ -29,7 +29,7 @@ type ecPrivateKey struct { } // ParseECPrivateKey parses an ASN.1 Elliptic Curve Private Key Structure. -func ParseECPrivateKey(der []byte) (key *ecdsa.PrivateKey, err error) { +func ParseECPrivateKey(der []byte) (*ecdsa.PrivateKey, error) { return parseECPrivateKey(nil, der) } diff --git a/libgo/go/crypto/x509/verify.go b/libgo/go/crypto/x509/verify.go index 27e9bbf..85c083f 100644 --- a/libgo/go/crypto/x509/verify.go +++ b/libgo/go/crypto/x509/verify.go @@ -117,10 +117,16 @@ func (e UnknownAuthorityError) Error() string { } // SystemRootsError results when we fail to load the system root certificates. -type SystemRootsError struct{} +type SystemRootsError struct { + Err error +} -func (SystemRootsError) Error() string { - return "x509: failed to load system roots and no roots provided" +func (se SystemRootsError) Error() string { + msg := "x509: failed to load system roots and no roots provided" + if se.Err != nil { + return msg + "; " + se.Err.Error() + } + return msg } // errNotParsed is returned when a certificate without ASN.1 contents is @@ -179,7 +185,7 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V // being valid for encryption only, but no-one noticed. Another // European CA marked its signature keys as not being valid for // signatures. A different CA marked its own trusted root certificate - // as being invalid for certificate signing. Another national CA + // as being invalid for certificate signing. Another national CA // distributed a certificate to be used to encrypt data for the // country’s tax authority that was marked as only being usable for // digital signatures but not for encryption. Yet another CA reversed @@ -240,7 +246,7 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e if opts.Roots == nil { opts.Roots = systemRootsPool() if opts.Roots == nil { - return nil, SystemRootsError{} + return nil, SystemRootsError{systemRootsErr} } } diff --git a/libgo/go/crypto/x509/verify_test.go b/libgo/go/crypto/x509/verify_test.go index 694c140..bacf7de 100644 --- a/libgo/go/crypto/x509/verify_test.go +++ b/libgo/go/crypto/x509/verify_test.go @@ -382,7 +382,7 @@ func testVerify(t *testing.T, useSystemRoots bool) { continue } for k, cert := range chain { - if strings.Index(nameToKey(&cert.Subject), expectedChain[k]) == -1 { + if !strings.Contains(nameToKey(&cert.Subject), expectedChain[k]) { continue TryNextExpected } } @@ -650,50 +650,6 @@ um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14= -----END CERTIFICATE-----` -const startComRootSHA256 = `-----BEGIN CERTIFICATE----- -MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEW -MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg -Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM3WhcNMzYwOTE3MTk0NjM2WjB9 -MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi -U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh -cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA -A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk -pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf -OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C -Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT -Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi -HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM -Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w -+2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ -Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 -Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B -26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID -AQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD -VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFul -F2mHMMo0aEPQQa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCC -ATgwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w -ZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2ludGVybWVk -aWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENvbW1lcmNpYWwgKFN0 -YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0aGUg -c2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93 -d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgG -CWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1 -dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5fPGFf59Jb2vKXfuM/gTF -wWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWmN3PH/UvS -Ta0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst -0OcNOrg+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNc -pRJvkrKTlMeIFw6Ttn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKl -CcWw0bdT82AUuoVpaiF8H3VhFyAXe2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVF -P0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA2MFrLH9ZXF2RsXAiV+uKa0hK -1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBsHvUwyKMQ5bLm -KhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE -JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ -8dCAWZvLMdibD4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnm -fyWl8kgAwKQB2j8= ------END CERTIFICATE-----` - const smimeLeaf = `-----BEGIN CERTIFICATE----- MIIFBjCCA+6gAwIBAgISESFvrjT8XcJTEe6rBlPptILlMA0GCSqGSIb3DQEBBQUA MFQxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMSowKAYD diff --git a/libgo/go/crypto/x509/x509.go b/libgo/go/crypto/x509/x509.go index d9288bb..9ad3cf2 100644 --- a/libgo/go/crypto/x509/x509.go +++ b/libgo/go/crypto/x509/x509.go @@ -36,6 +36,12 @@ type pkixPublicKey struct { // ParsePKIXPublicKey parses a DER encoded public key. These values are // typically found in PEM blocks with "BEGIN PUBLIC KEY". +// +// Supported key types include RSA, DSA, and ECDSA. Unknown key +// types result in an error. +// +// On success, pub will be of type *rsa.PublicKey, *dsa.PublicKey, +// or *ecdsa.PublicKey. func ParsePKIXPublicKey(derBytes []byte) (pub interface{}, err error) { var pki publicKeyInfo if rest, err := asn1.Unmarshal(derBytes, &pki); err != nil { @@ -120,7 +126,7 @@ type certificate struct { type tbsCertificate struct { Raw asn1.RawContent - Version int `asn1:"optional,explicit,default:1,tag:0"` + Version int `asn1:"optional,explicit,default:0,tag:0"` SerialNumber *big.Int SignatureAlgorithm pkix.AlgorithmIdentifier Issuer asn1.RawValue @@ -264,7 +270,7 @@ var ( oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12} oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13} oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3} - oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 4, 3, 2} + oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 2} oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1} oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2} oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3} @@ -635,7 +641,7 @@ var entrustBrokenSPKI = []byte{ // CheckSignatureFrom verifies that the signature on c is a valid signature // from parent. -func (c *Certificate) CheckSignatureFrom(parent *Certificate) (err error) { +func (c *Certificate) CheckSignatureFrom(parent *Certificate) error { // RFC 5280, 4.2.1.9: // "If the basic constraints extension is not present in a version 3 // certificate, or the extension is present but the cA boolean is not @@ -663,7 +669,7 @@ func (c *Certificate) CheckSignatureFrom(parent *Certificate) (err error) { // CheckSignature verifies that signature is a valid signature over signed from // c's public key. -func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature []byte) (err error) { +func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature []byte) error { return checkSignature(algo, signed, signature, c.PublicKey) } @@ -731,7 +737,7 @@ func checkSignature(algo SignatureAlgorithm, signed, signature []byte, publicKey } // CheckCRLSignature checks that the signature in crl is from c. -func (c *Certificate) CheckCRLSignature(crl *pkix.CertificateList) (err error) { +func (c *Certificate) CheckCRLSignature(crl *pkix.CertificateList) error { algo := getSignatureAlgorithmFromOID(crl.SignatureAlgorithm.Algorithm) return c.CheckSignature(algo, crl.TBSCertList.Raw, crl.SignatureValue.RightAlign()) } @@ -1127,7 +1133,7 @@ func parseCertificate(in *certificate) (*Certificate, error) { if rest, err := asn1.Unmarshal(e.Value, &keyid); err != nil { return nil, err } else if len(rest) != 0 { - return nil, errors.New("x509: trailing data after X.509 authority key-id") + return nil, errors.New("x509: trailing data after X.509 key-id") } out.SubjectKeyId = keyid @@ -1581,21 +1587,21 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv return nil, err } - if len(parent.SubjectKeyId) > 0 { - template.AuthorityKeyId = parent.SubjectKeyId - } - - extensions, err := buildExtensions(template) + asn1Issuer, err := subjectBytes(parent) if err != nil { return } - asn1Issuer, err := subjectBytes(parent) + asn1Subject, err := subjectBytes(template) if err != nil { return } - asn1Subject, err := subjectBytes(template) + if !bytes.Equal(asn1Issuer, asn1Subject) && len(parent.SubjectKeyId) > 0 { + template.AuthorityKeyId = parent.SubjectKeyId + } + + extensions, err := buildExtensions(template) if err != nil { return } @@ -1648,7 +1654,7 @@ var pemType = "X509 CRL" // encoded CRLs will appear where they should be DER encoded, so this function // will transparently handle PEM encoding as long as there isn't any leading // garbage. -func ParseCRL(crlBytes []byte) (certList *pkix.CertificateList, err error) { +func ParseCRL(crlBytes []byte) (*pkix.CertificateList, error) { if bytes.HasPrefix(crlBytes, pemCRLPrefix) { block, _ := pem.Decode(crlBytes) if block != nil && block.Type == pemType { @@ -1659,8 +1665,8 @@ func ParseCRL(crlBytes []byte) (certList *pkix.CertificateList, err error) { } // ParseDERCRL parses a DER encoded CRL from the given bytes. -func ParseDERCRL(derBytes []byte) (certList *pkix.CertificateList, err error) { - certList = new(pkix.CertificateList) +func ParseDERCRL(derBytes []byte) (*pkix.CertificateList, error) { + certList := new(pkix.CertificateList) if rest, err := asn1.Unmarshal(derBytes, certList); err != nil { return nil, err } else if len(rest) != 0 { @@ -1790,6 +1796,9 @@ var oidExtensionRequest = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 14} func newRawAttributes(attributes []pkix.AttributeTypeAndValueSET) ([]asn1.RawValue, error) { var rawAttributes []asn1.RawValue b, err := asn1.Marshal(attributes) + if err != nil { + return nil, err + } rest, err := asn1.Unmarshal(b, &rawAttributes) if err != nil { return nil, err @@ -1847,8 +1856,8 @@ func parseCSRExtensions(rawAttributes []asn1.RawValue) ([]pkix.Extension, error) return ret, nil } -// CreateCertificateRequest creates a new certificate based on a template. The -// following members of template are used: Subject, Attributes, +// CreateCertificateRequest creates a new certificate request based on a template. +// The following members of template are used: Subject, Attributes, // SignatureAlgorithm, Extensions, DNSNames, EmailAddresses, and IPAddresses. // The private key is the private key of the signer. // @@ -2065,7 +2074,7 @@ func parseCertificateRequest(in *certificateRequest) (*CertificateRequest, error return out, nil } -// CheckSignature verifies that the signature on c is a valid signature -func (c *CertificateRequest) CheckSignature() (err error) { +// CheckSignature reports whether the signature on c is valid. +func (c *CertificateRequest) CheckSignature() error { return checkSignature(c.SignatureAlgorithm, c.RawTBSCertificateRequest, c.Signature, c.PublicKey) } diff --git a/libgo/go/crypto/x509/x509_test.go b/libgo/go/crypto/x509/x509_test.go index d1ef027..c6448d3 100644 --- a/libgo/go/crypto/x509/x509_test.go +++ b/libgo/go/crypto/x509/x509_test.go @@ -96,6 +96,17 @@ tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V -----END RSA PRIVATE KEY----- ` +var testPrivateKey *rsa.PrivateKey + +func init() { + block, _ := pem.Decode([]byte(pemPrivateKey)) + + var err error + if testPrivateKey, err = ParsePKCS1PrivateKey(block.Bytes); err != nil { + panic("Failed to parse private key: " + err.Error()) + } +} + func bigFromString(s string) *big.Int { ret := new(big.Int) ret.SetString(s, 10) @@ -314,12 +325,6 @@ var certBytes = "308203223082028ba00302010202106edf0d9499fd4533dd1297fc42a93be13 func TestCreateSelfSignedCertificate(t *testing.T) { random := rand.Reader - block, _ := pem.Decode([]byte(pemPrivateKey)) - rsaPriv, err := ParsePKCS1PrivateKey(block.Bytes) - if err != nil { - t.Fatalf("Failed to parse private key: %s", err) - } - ecdsaPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { t.Fatalf("Failed to generate ECDSA key: %s", err) @@ -331,9 +336,9 @@ func TestCreateSelfSignedCertificate(t *testing.T) { checkSig bool sigAlgo SignatureAlgorithm }{ - {"RSA/RSA", &rsaPriv.PublicKey, rsaPriv, true, SHA1WithRSA}, - {"RSA/ECDSA", &rsaPriv.PublicKey, ecdsaPriv, false, ECDSAWithSHA384}, - {"ECDSA/RSA", &ecdsaPriv.PublicKey, rsaPriv, false, SHA256WithRSA}, + {"RSA/RSA", &testPrivateKey.PublicKey, testPrivateKey, true, SHA1WithRSA}, + {"RSA/ECDSA", &testPrivateKey.PublicKey, ecdsaPriv, false, ECDSAWithSHA384}, + {"ECDSA/RSA", &ecdsaPriv.PublicKey, testPrivateKey, false, SHA256WithRSA}, {"ECDSA/ECDSA", &ecdsaPriv.PublicKey, ecdsaPriv, true, ECDSAWithSHA1}, } @@ -488,7 +493,7 @@ func TestCreateSelfSignedCertificate(t *testing.T) { t.Errorf("%s: ExtraExtensions didn't override SubjectKeyId", test.name) } - if bytes.Index(derBytes, extraExtensionData) == -1 { + if !bytes.Contains(derBytes, extraExtensionData) { t.Errorf("%s: didn't find extra extension in DER output", test.name) } @@ -874,12 +879,6 @@ const pemCRLBase64 = "LS0tLS1CRUdJTiBYNTA5IENSTC0tLS0tDQpNSUlCOWpDQ0FWOENBUUV3RF func TestCreateCertificateRequest(t *testing.T) { random := rand.Reader - block, _ := pem.Decode([]byte(pemPrivateKey)) - rsaPriv, err := ParsePKCS1PrivateKey(block.Bytes) - if err != nil { - t.Fatalf("Failed to parse private key: %s", err) - } - ecdsa256Priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { t.Fatalf("Failed to generate ECDSA key: %s", err) @@ -900,7 +899,7 @@ func TestCreateCertificateRequest(t *testing.T) { priv interface{} sigAlgo SignatureAlgorithm }{ - {"RSA", rsaPriv, SHA1WithRSA}, + {"RSA", testPrivateKey, SHA1WithRSA}, {"ECDSA-256", ecdsa256Priv, ECDSAWithSHA1}, {"ECDSA-384", ecdsa384Priv, ECDSAWithSHA1}, {"ECDSA-521", ecdsa521Priv, ECDSAWithSHA1}, @@ -951,13 +950,7 @@ func TestCreateCertificateRequest(t *testing.T) { } func marshalAndParseCSR(t *testing.T, template *CertificateRequest) *CertificateRequest { - block, _ := pem.Decode([]byte(pemPrivateKey)) - rsaPriv, err := ParsePKCS1PrivateKey(block.Bytes) - if err != nil { - t.Fatal(err) - } - - derBytes, err := CreateCertificateRequest(rand.Reader, template, rsaPriv) + derBytes, err := CreateCertificateRequest(rand.Reader, template, testPrivateKey) if err != nil { t.Fatal(err) } @@ -1113,13 +1106,25 @@ func TestCriticalFlagInCSRRequestedExtensions(t *testing.T) { } } -func TestMaxPathLen(t *testing.T) { - block, _ := pem.Decode([]byte(pemPrivateKey)) - rsaPriv, err := ParsePKCS1PrivateKey(block.Bytes) +// serialiseAndParse generates a self-signed certificate from template and +// returns a parsed version of it. +func serialiseAndParse(t *testing.T, template *Certificate) *Certificate { + derBytes, err := CreateCertificate(rand.Reader, template, template, &testPrivateKey.PublicKey, testPrivateKey) if err != nil { - t.Fatalf("Failed to parse private key: %s", err) + t.Fatalf("failed to create certificate: %s", err) + return nil } + cert, err := ParseCertificate(derBytes) + if err != nil { + t.Fatalf("failed to parse certificate: %s", err) + return nil + } + + return cert +} + +func TestMaxPathLen(t *testing.T) { template := &Certificate{ SerialNumber: big.NewInt(1), Subject: pkix.Name{ @@ -1132,23 +1137,7 @@ func TestMaxPathLen(t *testing.T) { IsCA: true, } - serialiseAndParse := func(template *Certificate) *Certificate { - derBytes, err := CreateCertificate(rand.Reader, template, template, &rsaPriv.PublicKey, rsaPriv) - if err != nil { - t.Fatalf("failed to create certificate: %s", err) - return nil - } - - cert, err := ParseCertificate(derBytes) - if err != nil { - t.Fatalf("failed to parse certificate: %s", err) - return nil - } - - return cert - } - - cert1 := serialiseAndParse(template) + cert1 := serialiseAndParse(t, template) if m := cert1.MaxPathLen; m != -1 { t.Errorf("Omitting MaxPathLen didn't turn into -1, got %d", m) } @@ -1157,7 +1146,7 @@ func TestMaxPathLen(t *testing.T) { } template.MaxPathLen = 1 - cert2 := serialiseAndParse(template) + cert2 := serialiseAndParse(t, template) if m := cert2.MaxPathLen; m != 1 { t.Errorf("Setting MaxPathLen didn't work. Got %d but set 1", m) } @@ -1167,7 +1156,7 @@ func TestMaxPathLen(t *testing.T) { template.MaxPathLen = 0 template.MaxPathLenZero = true - cert3 := serialiseAndParse(template) + cert3 := serialiseAndParse(t, template) if m := cert3.MaxPathLen; m != 0 { t.Errorf("Setting MaxPathLenZero didn't work, got %d", m) } @@ -1176,6 +1165,30 @@ func TestMaxPathLen(t *testing.T) { } } +func TestNoAuthorityKeyIdInSelfSignedCert(t *testing.T) { + template := &Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{ + CommonName: "Σ Acme Co", + }, + NotBefore: time.Unix(1000, 0), + NotAfter: time.Unix(100000, 0), + + BasicConstraintsValid: true, + IsCA: true, + SubjectKeyId: []byte{1, 2, 3, 4}, + } + + if cert := serialiseAndParse(t, template); len(cert.AuthorityKeyId) != 0 { + t.Fatalf("self-signed certificate contained default authority key id") + } + + template.AuthorityKeyId = []byte{1, 2, 3, 4} + if cert := serialiseAndParse(t, template); len(cert.AuthorityKeyId) == 0 { + t.Fatalf("self-signed certificate erased explicit authority key id") + } +} + func TestASN1BitLength(t *testing.T) { tests := []struct { bytes []byte |