summaryrefslogtreecommitdiff
path: root/src/pkg/crypto
diff options
context:
space:
mode:
authorMichael Stapelberg <stapelberg@debian.org>2013-03-04 21:27:36 +0100
committerMichael Stapelberg <michael@stapelberg.de>2013-03-04 21:27:36 +0100
commit04b08da9af0c450d645ab7389d1467308cfc2db8 (patch)
treedb247935fa4f2f94408edc3acd5d0d4f997aa0d8 /src/pkg/crypto
parent917c5fb8ec48e22459d77e3849e6d388f93d3260 (diff)
downloadgolang-04b08da9af0c450d645ab7389d1467308cfc2db8.tar.gz
Imported Upstream version 1.1~hg20130304upstream/1.1_hg20130304
Diffstat (limited to 'src/pkg/crypto')
-rw-r--r--src/pkg/crypto/aes/aes_test.go33
-rw-r--r--src/pkg/crypto/aes/asm_amd64.s287
-rw-r--r--src/pkg/crypto/aes/block.go6
-rw-r--r--src/pkg/crypto/aes/cipher.go8
-rw-r--r--src/pkg/crypto/aes/cipher_asm.go46
-rw-r--r--src/pkg/crypto/aes/cipher_generic.go19
-rw-r--r--src/pkg/crypto/cipher/cbc.go18
-rw-r--r--src/pkg/crypto/cipher/cfb.go6
-rw-r--r--src/pkg/crypto/cipher/cipher_test.go36
-rw-r--r--src/pkg/crypto/cipher/ctr.go2
-rw-r--r--src/pkg/crypto/cipher/example_test.go283
-rw-r--r--src/pkg/crypto/cipher/io.go6
-rw-r--r--src/pkg/crypto/des/des_test.go18
-rw-r--r--src/pkg/crypto/ecdsa/ecdsa.go6
-rw-r--r--src/pkg/crypto/ecdsa/ecdsa_test.go256
-rw-r--r--src/pkg/crypto/ecdsa/testdata/SigVer.rsp.bz2bin0 -> 95485 bytes
-rw-r--r--src/pkg/crypto/elliptic/elliptic.go92
-rw-r--r--src/pkg/crypto/elliptic/elliptic_test.go38
-rw-r--r--src/pkg/crypto/elliptic/p224.go91
-rw-r--r--src/pkg/crypto/hmac/hmac.go32
-rw-r--r--src/pkg/crypto/hmac/hmac_test.go19
-rw-r--r--src/pkg/crypto/md5/gen.go300
-rw-r--r--src/pkg/crypto/md5/md5.go35
-rw-r--r--src/pkg/crypto/md5/md5_test.go62
-rw-r--r--src/pkg/crypto/md5/md5block.go364
-rw-r--r--src/pkg/crypto/rand/example_test.go29
-rw-r--r--src/pkg/crypto/rand/rand_test.go16
-rw-r--r--src/pkg/crypto/rand/rand_unix.go20
-rw-r--r--src/pkg/crypto/rand/rand_windows.go4
-rw-r--r--src/pkg/crypto/rand/util.go61
-rw-r--r--src/pkg/crypto/rc4/rc4.go11
-rw-r--r--src/pkg/crypto/rc4/rc4_amd64.s53
-rw-r--r--src/pkg/crypto/rc4/rc4_arm.s58
-rw-r--r--src/pkg/crypto/rc4/rc4_asm.go18
-rw-r--r--src/pkg/crypto/rc4/rc4_ref.go20
-rw-r--r--src/pkg/crypto/rc4/rc4_test.go60
-rw-r--r--src/pkg/crypto/rsa/pkcs1v15.go42
-rw-r--r--src/pkg/crypto/rsa/pkcs1v15_test.go8
-rw-r--r--src/pkg/crypto/rsa/rsa.go92
-rw-r--r--src/pkg/crypto/rsa/rsa_test.go57
-rw-r--r--src/pkg/crypto/sha1/sha1.go39
-rw-r--r--src/pkg/crypto/sha1/sha1_test.go32
-rw-r--r--src/pkg/crypto/sha1/sha1block.go51
-rw-r--r--src/pkg/crypto/sha256/sha256.go83
-rw-r--r--src/pkg/crypto/sha256/sha256_test.go25
-rw-r--r--src/pkg/crypto/sha256/sha256block.go17
-rw-r--r--src/pkg/crypto/sha512/sha512.go83
-rw-r--r--src/pkg/crypto/sha512/sha512_test.go25
-rw-r--r--src/pkg/crypto/sha512/sha512block.go16
-rw-r--r--src/pkg/crypto/tls/cipher_suites.go4
-rw-r--r--src/pkg/crypto/tls/common.go25
-rw-r--r--src/pkg/crypto/tls/conn.go99
-rw-r--r--src/pkg/crypto/tls/generate_cert.go60
-rw-r--r--src/pkg/crypto/tls/handshake_client.go9
-rw-r--r--src/pkg/crypto/tls/handshake_client_test.go234
-rw-r--r--src/pkg/crypto/tls/handshake_messages.go108
-rw-r--r--src/pkg/crypto/tls/handshake_messages_test.go34
-rw-r--r--src/pkg/crypto/tls/handshake_server.go534
-rw-r--r--src/pkg/crypto/tls/handshake_server_test.go2369
-rw-r--r--src/pkg/crypto/tls/parse-gnutls-cli-debug-log.py57
-rw-r--r--src/pkg/crypto/tls/prf.go21
-rw-r--r--src/pkg/crypto/tls/prf_test.go15
-rw-r--r--src/pkg/crypto/tls/root_test.go61
-rw-r--r--src/pkg/crypto/tls/ticket.go182
-rw-r--r--src/pkg/crypto/tls/tls.go80
-rw-r--r--src/pkg/crypto/tls/tls_test.go107
-rw-r--r--src/pkg/crypto/x509/cert_pool.go2
-rw-r--r--src/pkg/crypto/x509/pem_decrypt.go233
-rw-r--r--src/pkg/crypto/x509/pem_decrypt_test.go223
-rw-r--r--src/pkg/crypto/x509/pkcs8.go22
-rw-r--r--src/pkg/crypto/x509/pkcs8_test.go18
-rw-r--r--src/pkg/crypto/x509/root_darwin.go9
-rw-r--r--src/pkg/crypto/x509/root_plan9.go33
-rw-r--r--src/pkg/crypto/x509/root_stub.go3
-rw-r--r--src/pkg/crypto/x509/root_unix.go6
-rw-r--r--src/pkg/crypto/x509/root_windows.go9
-rw-r--r--src/pkg/crypto/x509/sec1.go69
-rw-r--r--src/pkg/crypto/x509/sec1_test.go22
-rw-r--r--src/pkg/crypto/x509/verify.go155
-rw-r--r--src/pkg/crypto/x509/verify_test.go246
-rw-r--r--src/pkg/crypto/x509/x509.go475
-rw-r--r--src/pkg/crypto/x509/x509_test.go296
82 files changed, 6640 insertions, 2163 deletions
diff --git a/src/pkg/crypto/aes/aes_test.go b/src/pkg/crypto/aes/aes_test.go
index e500c666d..6261dd09f 100644
--- a/src/pkg/crypto/aes/aes_test.go
+++ b/src/pkg/crypto/aes/aes_test.go
@@ -221,7 +221,10 @@ L:
if tt.dec != nil {
dec = make([]uint32, len(tt.dec))
}
- expandKey(tt.key, enc, dec)
+ // This test could only test Go version of expandKey because asm
+ // version might use different memory layout for expanded keys
+ // This is OK because we don't expose expanded keys to the outside
+ expandKeyGo(tt.key, enc, dec)
for j, v := range enc {
if v != tt.enc[j] {
t.Errorf("key %d: enc[%d] = %#x, want %#x", i, j, v, tt.enc[j])
@@ -352,15 +355,39 @@ func TestCipherDecrypt(t *testing.T) {
}
func BenchmarkEncrypt(b *testing.B) {
- b.StopTimer()
tt := encryptTests[0]
c, err := NewCipher(tt.key)
if err != nil {
b.Fatal("NewCipher:", err)
}
out := make([]byte, len(tt.in))
- b.StartTimer()
+ b.SetBytes(int64(len(out)))
+ b.ResetTimer()
for i := 0; i < b.N; i++ {
c.Encrypt(out, tt.in)
}
}
+
+func BenchmarkDecrypt(b *testing.B) {
+ tt := encryptTests[0]
+ c, err := NewCipher(tt.key)
+ if err != nil {
+ b.Fatal("NewCipher:", err)
+ }
+ out := make([]byte, len(tt.out))
+ b.SetBytes(int64(len(out)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ c.Decrypt(out, tt.out)
+ }
+}
+
+func BenchmarkExpand(b *testing.B) {
+ tt := encryptTests[0]
+ n := len(tt.key) + 28
+ c := &aesCipher{make([]uint32, n), make([]uint32, n)}
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ expandKey(tt.key, c.enc, c.dec)
+ }
+}
diff --git a/src/pkg/crypto/aes/asm_amd64.s b/src/pkg/crypto/aes/asm_amd64.s
new file mode 100644
index 000000000..25decf978
--- /dev/null
+++ b/src/pkg/crypto/aes/asm_amd64.s
@@ -0,0 +1,287 @@
+// 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.
+
+// func hasAsm() bool
+// returns whether AES-NI is supported
+TEXT ·hasAsm(SB),7,$0
+ XORQ AX, AX
+ INCL AX
+ CPUID
+ SHRQ $25, CX
+ ANDQ $1, CX
+ MOVB CX, ret+0(FP)
+ RET
+
+// func encryptBlockAsm(nr int, xk *uint32, dst, src *byte)
+TEXT ·encryptBlockAsm(SB),7,$0
+ MOVQ nr+0(FP), CX
+ MOVQ xk+8(FP), AX
+ MOVQ dst+16(FP), DX
+ MOVQ src+24(FP), BX
+ MOVUPS 0(AX), X1
+ MOVUPS 0(BX), X0
+ ADDQ $16, AX
+ PXOR X1, X0
+ SUBQ $12, CX
+ JE Lenc196
+ JB Lenc128
+Lenc256:
+ MOVUPS 0(AX), X1
+ AESENC X1, X0
+ MOVUPS 16(AX), X1
+ AESENC X1, X0
+ ADDQ $32, AX
+Lenc196:
+ MOVUPS 0(AX), X1
+ AESENC X1, X0
+ MOVUPS 16(AX), X1
+ AESENC X1, X0
+ ADDQ $32, AX
+Lenc128:
+ MOVUPS 0(AX), X1
+ AESENC X1, X0
+ MOVUPS 16(AX), X1
+ AESENC X1, X0
+ MOVUPS 32(AX), X1
+ AESENC X1, X0
+ MOVUPS 48(AX), X1
+ AESENC X1, X0
+ MOVUPS 64(AX), X1
+ AESENC X1, X0
+ MOVUPS 80(AX), X1
+ AESENC X1, X0
+ MOVUPS 96(AX), X1
+ AESENC X1, X0
+ MOVUPS 112(AX), X1
+ AESENC X1, X0
+ MOVUPS 128(AX), X1
+ AESENC X1, X0
+ MOVUPS 144(AX), X1
+ AESENCLAST X1, X0
+ MOVUPS X0, 0(DX)
+ RET
+
+// func decryptBlockAsm(nr int, xk *uint32, dst, src *byte)
+TEXT ·decryptBlockAsm(SB),7,$0
+ MOVQ nr+0(FP), CX
+ MOVQ xk+8(FP), AX
+ MOVQ dst+16(FP), DX
+ MOVQ src+24(FP), BX
+ MOVUPS 0(AX), X1
+ MOVUPS 0(BX), X0
+ ADDQ $16, AX
+ PXOR X1, X0
+ SUBQ $12, CX
+ JE Ldec196
+ JB Ldec128
+Ldec256:
+ MOVUPS 0(AX), X1
+ AESDEC X1, X0
+ MOVUPS 16(AX), X1
+ AESDEC X1, X0
+ ADDQ $32, AX
+Ldec196:
+ MOVUPS 0(AX), X1
+ AESDEC X1, X0
+ MOVUPS 16(AX), X1
+ AESDEC X1, X0
+ ADDQ $32, AX
+Ldec128:
+ MOVUPS 0(AX), X1
+ AESDEC X1, X0
+ MOVUPS 16(AX), X1
+ AESDEC X1, X0
+ MOVUPS 32(AX), X1
+ AESDEC X1, X0
+ MOVUPS 48(AX), X1
+ AESDEC X1, X0
+ MOVUPS 64(AX), X1
+ AESDEC X1, X0
+ MOVUPS 80(AX), X1
+ AESDEC X1, X0
+ MOVUPS 96(AX), X1
+ AESDEC X1, X0
+ MOVUPS 112(AX), X1
+ AESDEC X1, X0
+ MOVUPS 128(AX), X1
+ AESDEC X1, X0
+ MOVUPS 144(AX), X1
+ AESDECLAST X1, X0
+ MOVUPS X0, 0(DX)
+ RET
+
+// func expandKeyAsm(nr int, key *byte, enc, dec *uint32) {
+// Note that round keys are stored in uint128 format, not uint32
+TEXT ·expandKeyAsm(SB),7,$0
+ MOVQ nr+0(FP), CX
+ MOVQ key+8(FP), AX
+ MOVQ enc+16(FP), BX
+ MOVQ dec+24(FP), DX
+ MOVUPS (AX), X0
+ // enc
+ MOVUPS X0, (BX)
+ ADDQ $16, BX
+ PXOR X4, X4 // _expand_key_* expect X4 to be zero
+ CMPL CX, $12
+ JE Lexp_enc196
+ JB Lexp_enc128
+Lexp_enc256:
+ MOVUPS 16(AX), X2
+ MOVUPS X2, (BX)
+ ADDQ $16, BX
+ AESKEYGENASSIST $0x01, X2, X1
+ CALL _expand_key_256a<>(SB)
+ AESKEYGENASSIST $0x01, X0, X1
+ CALL _expand_key_256b<>(SB)
+ AESKEYGENASSIST $0x02, X2, X1
+ CALL _expand_key_256a<>(SB)
+ AESKEYGENASSIST $0x02, X0, X1
+ CALL _expand_key_256b<>(SB)
+ AESKEYGENASSIST $0x04, X2, X1
+ CALL _expand_key_256a<>(SB)
+ AESKEYGENASSIST $0x04, X0, X1
+ CALL _expand_key_256b<>(SB)
+ AESKEYGENASSIST $0x08, X2, X1
+ CALL _expand_key_256a<>(SB)
+ AESKEYGENASSIST $0x08, X0, X1
+ CALL _expand_key_256b<>(SB)
+ AESKEYGENASSIST $0x10, X2, X1
+ CALL _expand_key_256a<>(SB)
+ AESKEYGENASSIST $0x10, X0, X1
+ CALL _expand_key_256b<>(SB)
+ AESKEYGENASSIST $0x20, X2, X1
+ CALL _expand_key_256a<>(SB)
+ AESKEYGENASSIST $0x20, X0, X1
+ CALL _expand_key_256b<>(SB)
+ AESKEYGENASSIST $0x40, X2, X1
+ CALL _expand_key_256a<>(SB)
+ JMP Lexp_dec
+Lexp_enc196:
+ MOVQ 16(AX), X2
+ AESKEYGENASSIST $0x01, X2, X1
+ CALL _expand_key_192a<>(SB)
+ AESKEYGENASSIST $0x02, X2, X1
+ CALL _expand_key_192b<>(SB)
+ AESKEYGENASSIST $0x04, X2, X1
+ CALL _expand_key_192a<>(SB)
+ AESKEYGENASSIST $0x08, X2, X1
+ CALL _expand_key_192b<>(SB)
+ AESKEYGENASSIST $0x10, X2, X1
+ CALL _expand_key_192a<>(SB)
+ AESKEYGENASSIST $0x20, X2, X1
+ CALL _expand_key_192b<>(SB)
+ AESKEYGENASSIST $0x40, X2, X1
+ CALL _expand_key_192a<>(SB)
+ AESKEYGENASSIST $0x80, X2, X1
+ CALL _expand_key_192b<>(SB)
+ JMP Lexp_dec
+Lexp_enc128:
+ AESKEYGENASSIST $0x01, X0, X1
+ CALL _expand_key_128<>(SB)
+ AESKEYGENASSIST $0x02, X0, X1
+ CALL _expand_key_128<>(SB)
+ AESKEYGENASSIST $0x04, X0, X1
+ CALL _expand_key_128<>(SB)
+ AESKEYGENASSIST $0x08, X0, X1
+ CALL _expand_key_128<>(SB)
+ AESKEYGENASSIST $0x10, X0, X1
+ CALL _expand_key_128<>(SB)
+ AESKEYGENASSIST $0x20, X0, X1
+ CALL _expand_key_128<>(SB)
+ AESKEYGENASSIST $0x40, X0, X1
+ CALL _expand_key_128<>(SB)
+ AESKEYGENASSIST $0x80, X0, X1
+ CALL _expand_key_128<>(SB)
+ AESKEYGENASSIST $0x1b, X0, X1
+ CALL _expand_key_128<>(SB)
+ AESKEYGENASSIST $0x36, X0, X1
+ CALL _expand_key_128<>(SB)
+Lexp_dec:
+ // dec
+ SUBQ $16, BX
+ MOVUPS (BX), X1
+ MOVUPS X1, (DX)
+ DECQ CX
+Lexp_dec_loop:
+ MOVUPS -16(BX), X1
+ AESIMC X1, X0
+ MOVUPS X0, 16(DX)
+ SUBQ $16, BX
+ ADDQ $16, DX
+ DECQ CX
+ JNZ Lexp_dec_loop
+ MOVUPS -16(BX), X0
+ MOVUPS X0, 16(DX)
+ RET
+
+#define PSHUFD_X0_X0_ BYTE $0x66; BYTE $0x0f; BYTE $0x70; BYTE $0xc0
+#define PSHUFD_X1_X1_ BYTE $0x66; BYTE $0x0f; BYTE $0x70; BYTE $0xc9
+TEXT _expand_key_128<>(SB),7,$0
+ PSHUFD $0xff, X1, X1
+ SHUFPS $0x10, X0, X4
+ PXOR X4, X0
+ SHUFPS $0x8c, X0, X4
+ PXOR X4, X0
+ PXOR X1, X0
+ MOVUPS X0, (BX)
+ ADDQ $16, BX
+ RET
+
+#define PSLLDQ_X5_ BYTE $0x66; BYTE $0x0f; BYTE $0x73; BYTE $0xfd
+#define PSHUFD_X0_X3_ BYTE $0x66; BYTE $0x0f; BYTE $0x70; BYTE $0xd8
+TEXT _expand_key_192a<>(SB),7,$0
+ PSHUFD $0x55, X1, X1
+ SHUFPS $0x10, X0, X4
+ PXOR X4, X0
+ SHUFPS $0x8c, X0, X4
+ PXOR X4, X0
+ PXOR X1, X0
+
+ MOVAPS X2, X5
+ MOVAPS X2, X6
+ PSLLDQ_X5_; BYTE $0x4
+ PSHUFD $0xff, X0, X3
+ PXOR X3, X2
+ PXOR X5, X2
+
+ MOVAPS X0, X1
+ SHUFPS $0x44, X0, X6
+ MOVUPS X6, (BX)
+ SHUFPS $0x4e, X2, X1
+ MOVUPS X1, 16(BX)
+ ADDQ $32, BX
+ RET
+
+TEXT _expand_key_192b<>(SB),7,$0
+ PSHUFD $0x55, X1, X1
+ SHUFPS $0x10, X0, X4
+ PXOR X4, X0
+ SHUFPS $0x8c, X0, X4
+ PXOR X4, X0
+ PXOR X1, X0
+
+ MOVAPS X2, X5
+ PSLLDQ_X5_; BYTE $0x4
+ PSHUFD $0xff, X0, X3
+ PXOR X3, X2
+ PXOR X5, X2
+
+ MOVUPS X0, (BX)
+ ADDQ $16, BX
+ RET
+
+TEXT _expand_key_256a<>(SB),7,$0
+ JMP _expand_key_128<>(SB)
+
+TEXT _expand_key_256b<>(SB),7,$0
+ PSHUFD $0xaa, X1, X1
+ SHUFPS $0x10, X2, X4
+ PXOR X4, X2
+ SHUFPS $0x8c, X2, X4
+ PXOR X4, X2
+ PXOR X1, X2
+
+ MOVUPS X2, (BX)
+ ADDQ $16, BX
+ RET
diff --git a/src/pkg/crypto/aes/block.go b/src/pkg/crypto/aes/block.go
index b930787ce..57a7e9e25 100644
--- a/src/pkg/crypto/aes/block.go
+++ b/src/pkg/crypto/aes/block.go
@@ -37,7 +37,7 @@
package aes
// Encrypt one block from src into dst, using the expanded key xk.
-func encryptBlock(xk []uint32, dst, src []byte) {
+func encryptBlockGo(xk []uint32, dst, src []byte) {
var s0, s1, s2, s3, t0, t1, t2, t3 uint32
s0 = uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
@@ -82,7 +82,7 @@ func encryptBlock(xk []uint32, dst, src []byte) {
}
// Decrypt one block from src into dst, using the expanded key xk.
-func decryptBlock(xk []uint32, dst, src []byte) {
+func decryptBlockGo(xk []uint32, dst, src []byte) {
var s0, s1, s2, s3, t0, t1, t2, t3 uint32
s0 = uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
@@ -139,7 +139,7 @@ func rotw(w uint32) uint32 { return w<<8 | w>>24 }
// Key expansion algorithm. See FIPS-197, Figure 11.
// Their rcon[i] is our powx[i-1] << 24.
-func expandKey(key []byte, enc, dec []uint32) {
+func expandKeyGo(key []byte, enc, dec []uint32) {
// Encryption key setup.
var i int
nk := len(key) / 4
diff --git a/src/pkg/crypto/aes/cipher.go b/src/pkg/crypto/aes/cipher.go
index 7d307c93a..d931134a7 100644
--- a/src/pkg/crypto/aes/cipher.go
+++ b/src/pkg/crypto/aes/cipher.go
@@ -45,6 +45,10 @@ func NewCipher(key []byte) (cipher.Block, error) {
func (c *aesCipher) BlockSize() int { return BlockSize }
-func (c *aesCipher) Encrypt(dst, src []byte) { encryptBlock(c.enc, dst, src) }
+func (c *aesCipher) Encrypt(dst, src []byte) {
+ encryptBlock(c.enc, dst, src)
+}
-func (c *aesCipher) Decrypt(dst, src []byte) { decryptBlock(c.dec, dst, src) }
+func (c *aesCipher) Decrypt(dst, src []byte) {
+ decryptBlock(c.dec, dst, src)
+}
diff --git a/src/pkg/crypto/aes/cipher_asm.go b/src/pkg/crypto/aes/cipher_asm.go
new file mode 100644
index 000000000..21369fc38
--- /dev/null
+++ b/src/pkg/crypto/aes/cipher_asm.go
@@ -0,0 +1,46 @@
+// 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/src/pkg/crypto/aes/cipher_generic.go b/src/pkg/crypto/aes/cipher_generic.go
new file mode 100644
index 000000000..1714e0f1e
--- /dev/null
+++ b/src/pkg/crypto/aes/cipher_generic.go
@@ -0,0 +1,19 @@
+// 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
+
+func encryptBlock(xk []uint32, dst, src []byte) {
+ encryptBlockGo(xk, dst, src)
+}
+
+func decryptBlock(xk []uint32, dst, src []byte) {
+ decryptBlockGo(xk, dst, src)
+}
+
+func expandKey(key []byte, enc, dec []uint32) {
+ expandKeyGo(key, enc, dec)
+}
diff --git a/src/pkg/crypto/cipher/cbc.go b/src/pkg/crypto/cipher/cbc.go
index a48929cf5..913a5643f 100644
--- a/src/pkg/crypto/cipher/cbc.go
+++ b/src/pkg/crypto/cipher/cbc.go
@@ -33,12 +33,21 @@ type cbcEncrypter cbc
// mode, using the given Block. The length of iv must be the same as the
// Block's block size.
func NewCBCEncrypter(b Block, iv []byte) BlockMode {
+ if len(iv) != b.BlockSize() {
+ panic("cipher.NewCBCEncrypter: IV length must equal block size")
+ }
return (*cbcEncrypter)(newCBC(b, iv))
}
func (x *cbcEncrypter) BlockSize() int { return x.blockSize }
func (x *cbcEncrypter) CryptBlocks(dst, src []byte) {
+ if len(src)%x.blockSize != 0 {
+ panic("crypto/cipher: input not full blocks")
+ }
+ if len(dst) < len(src) {
+ panic("crypto/cipher: output smaller than input")
+ }
for len(src) > 0 {
for i := 0; i < x.blockSize; i++ {
x.iv[i] ^= src[i]
@@ -58,12 +67,21 @@ type cbcDecrypter cbc
// 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.
func NewCBCDecrypter(b Block, iv []byte) BlockMode {
+ if len(iv) != b.BlockSize() {
+ panic("cipher.NewCBCDecrypter: IV length must equal block size")
+ }
return (*cbcDecrypter)(newCBC(b, iv))
}
func (x *cbcDecrypter) BlockSize() int { return x.blockSize }
func (x *cbcDecrypter) CryptBlocks(dst, src []byte) {
+ if len(src)%x.blockSize != 0 {
+ panic("crypto/cipher: input not full blocks")
+ }
+ if len(dst) < len(src) {
+ panic("crypto/cipher: output smaller than input")
+ }
for len(src) > 0 {
x.b.Decrypt(x.tmp, src[:x.blockSize])
for i := 0; i < x.blockSize; i++ {
diff --git a/src/pkg/crypto/cipher/cfb.go b/src/pkg/crypto/cipher/cfb.go
index d14165a86..99006b546 100644
--- a/src/pkg/crypto/cipher/cfb.go
+++ b/src/pkg/crypto/cipher/cfb.go
@@ -17,6 +17,9 @@ type cfb struct {
// using the given Block. The iv must be the same length as the Block's block
// size.
func NewCFBEncrypter(block Block, iv []byte) Stream {
+ if len(iv) != block.BlockSize() {
+ panic("cipher.NewCBFEncrypter: IV length must equal block size")
+ }
return newCFB(block, iv, false)
}
@@ -24,6 +27,9 @@ func NewCFBEncrypter(block Block, iv []byte) Stream {
// using the given Block. The iv must be the same length as the Block's block
// size.
func NewCFBDecrypter(block Block, iv []byte) Stream {
+ if len(iv) != block.BlockSize() {
+ panic("cipher.NewCBFEncrypter: IV length must equal block size")
+ }
return newCFB(block, iv, true)
}
diff --git a/src/pkg/crypto/cipher/cipher_test.go b/src/pkg/crypto/cipher/cipher_test.go
new file mode 100644
index 000000000..8da5bce93
--- /dev/null
+++ b/src/pkg/crypto/cipher/cipher_test.go
@@ -0,0 +1,36 @@
+// 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.
+
+package cipher_test
+
+import (
+ "crypto/aes"
+ "crypto/cipher"
+ "testing"
+)
+
+func TestCryptBlocks(t *testing.T) {
+ buf := make([]byte, 16)
+ block, _ := aes.NewCipher(buf)
+
+ mode := cipher.NewCBCDecrypter(block, buf)
+ mustPanic(t, "crypto/cipher: input not full blocks", func() { mode.CryptBlocks(buf, buf[:3]) })
+ mustPanic(t, "crypto/cipher: output smaller than input", func() { mode.CryptBlocks(buf[:3], buf) })
+
+ mode = cipher.NewCBCEncrypter(block, buf)
+ mustPanic(t, "crypto/cipher: input not full blocks", func() { mode.CryptBlocks(buf, buf[:3]) })
+ mustPanic(t, "crypto/cipher: output smaller than input", func() { mode.CryptBlocks(buf[:3], buf) })
+}
+
+func mustPanic(t *testing.T, msg string, f func()) {
+ defer func() {
+ err := recover()
+ if err == nil {
+ t.Errorf("function did not panic, wanted %q", msg)
+ } else if err != msg {
+ t.Errorf("got panic %v, wanted %q", err, msg)
+ }
+ }()
+ f()
+}
diff --git a/src/pkg/crypto/cipher/ctr.go b/src/pkg/crypto/cipher/ctr.go
index 147b74fc2..d9ee9d827 100644
--- a/src/pkg/crypto/cipher/ctr.go
+++ b/src/pkg/crypto/cipher/ctr.go
@@ -23,7 +23,7 @@ type ctr struct {
// counter mode. The length of iv must be the same as the Block's block size.
func NewCTR(block Block, iv []byte) Stream {
if len(iv) != block.BlockSize() {
- panic("cipher.NewCTR: iv length must equal block size")
+ panic("cipher.NewCTR: IV length must equal block size")
}
return &ctr{
diff --git a/src/pkg/crypto/cipher/example_test.go b/src/pkg/crypto/cipher/example_test.go
new file mode 100644
index 000000000..e0027cac2
--- /dev/null
+++ b/src/pkg/crypto/cipher/example_test.go
@@ -0,0 +1,283 @@
+// 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 cipher_test
+
+import (
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/rand"
+ "encoding/hex"
+ "fmt"
+ "io"
+ "os"
+)
+
+func ExampleNewCBCDecrypter() {
+ key := []byte("example key 1234")
+ ciphertext, _ := hex.DecodeString("f363f3ccdcb12bb883abf484ba77d9cd7d32b5baecb3d4b1b3e0e4beffdb3ded")
+
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ panic(err)
+ }
+
+ // The IV needs to be unique, but not secure. Therefore it's common to
+ // include it at the beginning of the ciphertext.
+ if len(ciphertext) < aes.BlockSize {
+ panic("ciphertext too short")
+ }
+ iv := ciphertext[:aes.BlockSize]
+ ciphertext = ciphertext[aes.BlockSize:]
+
+ // CBC mode always works in whole blocks.
+ if len(ciphertext)%aes.BlockSize != 0 {
+ panic("ciphertext is not a multiple of the block size")
+ }
+
+ mode := cipher.NewCBCDecrypter(block, iv)
+
+ // CryptBlocks can work in-place if the two arguments are the same.
+ mode.CryptBlocks(ciphertext, ciphertext)
+
+ // If the original plaintext lengths are not a multiple of the block
+ // size, padding would have to be added when encrypting, which would be
+ // removed at this point. For an example, see
+ // https://tools.ietf.org/html/rfc5246#section-6.2.3.2. However, it's
+ // critical to note that ciphertexts must be authenticated (i.e. by
+ // using crypto/hmac) before being decrypted in order to avoid creating
+ // a padding oracle.
+
+ fmt.Printf("%s\n", ciphertext)
+ // Output: exampleplaintext
+}
+
+func ExampleNewCBCEncrypter() {
+ key := []byte("example key 1234")
+ plaintext := []byte("exampleplaintext")
+
+ // CBC mode works on blocks so plaintexts may need to be padded to the
+ // next whole block. For an example of such padding, see
+ // https://tools.ietf.org/html/rfc5246#section-6.2.3.2. Here we'll
+ // assume that the plaintext is already of the correct length.
+ if len(plaintext)%aes.BlockSize != 0 {
+ panic("plaintext is not a multiple of the block size")
+ }
+
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ panic(err)
+ }
+
+ // The IV needs to be unique, but not secure. Therefore it's common to
+ // include it at the beginning of the ciphertext.
+ ciphertext := make([]byte, aes.BlockSize+len(plaintext))
+ iv := ciphertext[:aes.BlockSize]
+ if _, err := io.ReadFull(rand.Reader, iv); err != nil {
+ panic(err)
+ }
+
+ mode := cipher.NewCBCEncrypter(block, iv)
+ mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)
+
+ // It's important to remember that ciphertexts must be authenticated
+ // (i.e. by using crypto/hmac) as well as being encrypted in order to
+ // be secure.
+
+ fmt.Printf("%x\n", ciphertext)
+}
+
+func ExampleNewCFBDecrypter() {
+ key := []byte("example key 1234")
+ ciphertext, _ := hex.DecodeString("22277966616d9bc47177bd02603d08c9a67d5380d0fe8cf3b44438dff7b9")
+
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ panic(err)
+ }
+
+ // The IV needs to be unique, but not secure. Therefore it's common to
+ // include it at the beginning of the ciphertext.
+ if len(ciphertext) < aes.BlockSize {
+ panic("ciphertext too short")
+ }
+ iv := ciphertext[:aes.BlockSize]
+ ciphertext = ciphertext[aes.BlockSize:]
+
+ stream := cipher.NewCFBDecrypter(block, iv)
+
+ // XORKeyStream can work in-place if the two arguments are the same.
+ stream.XORKeyStream(ciphertext, ciphertext)
+ fmt.Printf("%s", ciphertext)
+ // Output: some plaintext
+}
+
+func ExampleNewCFBEncrypter() {
+ key := []byte("example key 1234")
+ plaintext := []byte("some plaintext")
+
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ panic(err)
+ }
+
+ // The IV needs to be unique, but not secure. Therefore it's common to
+ // include it at the beginning of the ciphertext.
+ ciphertext := make([]byte, aes.BlockSize+len(plaintext))
+ iv := ciphertext[:aes.BlockSize]
+ if _, err := io.ReadFull(rand.Reader, iv); err != nil {
+ panic(err)
+ }
+
+ stream := cipher.NewCFBEncrypter(block, iv)
+ stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
+
+ // It's important to remember that ciphertexts must be authenticated
+ // (i.e. by using crypto/hmac) as well as being encrypted in order to
+ // be secure.
+}
+
+func ExampleNewCTR() {
+ key := []byte("example key 1234")
+ plaintext := []byte("some plaintext")
+
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ panic(err)
+ }
+
+ // The IV needs to be unique, but not secure. Therefore it's common to
+ // include it at the beginning of the ciphertext.
+ ciphertext := make([]byte, aes.BlockSize+len(plaintext))
+ iv := ciphertext[:aes.BlockSize]
+ if _, err := io.ReadFull(rand.Reader, iv); err != nil {
+ panic(err)
+ }
+
+ stream := cipher.NewCTR(block, iv)
+ stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
+
+ // It's important to remember that ciphertexts must be authenticated
+ // (i.e. by using crypto/hmac) as well as being encrypted in order to
+ // be secure.
+
+ // CTR mode is the same for both encryption and decryption, so we can
+ // also decrypt that ciphertext with NewCTR.
+
+ plaintext2 := make([]byte, len(plaintext))
+ stream = cipher.NewCTR(block, iv)
+ stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:])
+
+ fmt.Printf("%s\n", plaintext2)
+ // Output: some plaintext
+}
+
+func ExampleNewOFB() {
+ key := []byte("example key 1234")
+ plaintext := []byte("some plaintext")
+
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ panic(err)
+ }
+
+ // The IV needs to be unique, but not secure. Therefore it's common to
+ // include it at the beginning of the ciphertext.
+ ciphertext := make([]byte, aes.BlockSize+len(plaintext))
+ iv := ciphertext[:aes.BlockSize]
+ if _, err := io.ReadFull(rand.Reader, iv); err != nil {
+ panic(err)
+ }
+
+ stream := cipher.NewOFB(block, iv)
+ stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
+
+ // It's important to remember that ciphertexts must be authenticated
+ // (i.e. by using crypto/hmac) as well as being encrypted in order to
+ // be secure.
+
+ // OFB mode is the same for both encryption and decryption, so we can
+ // also decrypt that ciphertext with NewOFB.
+
+ plaintext2 := make([]byte, len(plaintext))
+ stream = cipher.NewOFB(block, iv)
+ stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:])
+
+ fmt.Printf("%s\n", plaintext2)
+ // Output: some plaintext
+}
+
+func ExampleStreamReader() {
+ key := []byte("example key 1234")
+
+ inFile, err := os.Open("encrypted-file")
+ if err != nil {
+ panic(err)
+ }
+ defer inFile.Close()
+
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ panic(err)
+ }
+
+ // If the key is unique for each ciphertext, then it's ok to use a zero
+ // IV.
+ var iv [aes.BlockSize]byte
+ stream := cipher.NewOFB(block, iv[:])
+
+ outFile, err := os.OpenFile("decrypted-file", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
+ if err != nil {
+ panic(err)
+ }
+ defer outFile.Close()
+
+ reader := &cipher.StreamReader{stream, inFile}
+ // Copy the input file to the output file, decrypting as we go.
+ if _, err := io.Copy(outFile, reader); err != nil {
+ panic(err)
+ }
+
+ // Note that this example is simplistic in that it omits any
+ // authentication of the encrypted data. It you were actually to use
+ // StreamReader in this manner, an attacker could flip arbitrary bits in
+ // the output.
+}
+
+func ExampleStreamWriter() {
+ key := []byte("example key 1234")
+
+ inFile, err := os.Open("plaintext-file")
+ if err != nil {
+ panic(err)
+ }
+ defer inFile.Close()
+
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ panic(err)
+ }
+
+ // If the key is unique for each ciphertext, then it's ok to use a zero
+ // IV.
+ var iv [aes.BlockSize]byte
+ stream := cipher.NewOFB(block, iv[:])
+
+ outFile, err := os.OpenFile("encrypted-file", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
+ if err != nil {
+ panic(err)
+ }
+ defer outFile.Close()
+
+ writer := &cipher.StreamWriter{stream, outFile, nil}
+ // Copy the input file to the output file, encrypting as we go.
+ if _, err := io.Copy(writer, inFile); err != nil {
+ panic(err)
+ }
+
+ // Note that this example is simplistic in that it omits any
+ // authentication of the encrypted data. It you were actually to use
+ // StreamReader in this manner, an attacker could flip arbitrary bits in
+ // the decrypted result.
+}
diff --git a/src/pkg/crypto/cipher/io.go b/src/pkg/crypto/cipher/io.go
index 76048fbf3..807e8daea 100644
--- a/src/pkg/crypto/cipher/io.go
+++ b/src/pkg/crypto/cipher/io.go
@@ -28,13 +28,10 @@ func (r StreamReader) Read(dst []byte) (n int, err error) {
type StreamWriter struct {
S Stream
W io.Writer
- Err error
+ Err error // unused
}
func (w StreamWriter) Write(src []byte) (n int, err error) {
- if w.Err != nil {
- return 0, w.Err
- }
c := make([]byte, len(src))
w.S.XORKeyStream(c, src)
n, err = w.W.Write(c)
@@ -42,7 +39,6 @@ func (w StreamWriter) Write(src []byte) (n int, err error) {
if err == nil { // should never happen
err = io.ErrShortWrite
}
- w.Err = err
}
return
}
diff --git a/src/pkg/crypto/des/des_test.go b/src/pkg/crypto/des/des_test.go
index e9fc23629..2e87e99b6 100644
--- a/src/pkg/crypto/des/des_test.go
+++ b/src/pkg/crypto/des/des_test.go
@@ -1503,3 +1503,21 @@ func TestSubstitutionTableKnownAnswerDecrypt(t *testing.T) {
}
}
}
+
+func ExampleNewTripleDESCipher() {
+ // NewTripleDESCipher can also be used when EDE2 is required by
+ // duplicating the first 8 bytes of the 16-byte key.
+ ede2Key := []byte("example key 1234")
+
+ var tripleDESKey []byte
+ tripleDESKey = append(tripleDESKey, ede2Key[:16]...)
+ tripleDESKey = append(tripleDESKey, ede2Key[:8]...)
+
+ _, err := NewTripleDESCipher(tripleDESKey)
+ if err != nil {
+ panic(err)
+ }
+
+ // See crypto/cipher for how to use a cipher.Block for encryption and
+ // decryption.
+}
diff --git a/src/pkg/crypto/ecdsa/ecdsa.go b/src/pkg/crypto/ecdsa/ecdsa.go
index 8508e3b4f..512d20c63 100644
--- a/src/pkg/crypto/ecdsa/ecdsa.go
+++ b/src/pkg/crypto/ecdsa/ecdsa.go
@@ -140,14 +140,16 @@ func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
w := new(big.Int).ModInverse(s, N)
u1 := e.Mul(e, w)
+ u1.Mod(u1, N)
u2 := w.Mul(r, w)
+ u2.Mod(u2, N)
x1, y1 := c.ScalarBaseMult(u1.Bytes())
x2, y2 := c.ScalarMult(pub.X, pub.Y, u2.Bytes())
- if x1.Cmp(x2) == 0 {
+ x, y := c.Add(x1, y1, x2, y2)
+ if x.Sign() == 0 && y.Sign() == 0 {
return false
}
- x, _ := c.Add(x1, y1, x2, y2)
x.Mod(x, N)
return x.Cmp(r) == 0
}
diff --git a/src/pkg/crypto/ecdsa/ecdsa_test.go b/src/pkg/crypto/ecdsa/ecdsa_test.go
index 3a2b3efba..0c0643193 100644
--- a/src/pkg/crypto/ecdsa/ecdsa_test.go
+++ b/src/pkg/crypto/ecdsa/ecdsa_test.go
@@ -5,11 +5,19 @@
package ecdsa
import (
+ "bufio"
+ "compress/bzip2"
"crypto/elliptic"
"crypto/rand"
"crypto/sha1"
+ "crypto/sha256"
+ "crypto/sha512"
"encoding/hex"
+ "hash"
+ "io"
"math/big"
+ "os"
+ "strings"
"testing"
)
@@ -72,156 +80,112 @@ func fromHex(s string) *big.Int {
return r
}
-// These test vectors were taken from
-// http://csrc.nist.gov/groups/STM/cavp/documents/dss/ecdsatestvectors.zip
-var testVectors = []struct {
- msg string
- Qx, Qy string
- r, s string
- ok bool
-}{
- {
- "09626b45493672e48f3d1226a3aff3201960e577d33a7f72c7eb055302db8fe8ed61685dd036b554942a5737cd1512cdf811ee0c00e6dd2f08c69f08643be396e85dafda664801e772cdb7396868ac47b172245b41986aa2648cb77fbbfa562581be06651355a0c4b090f9d17d8f0ab6cced4e0c9d386cf465a516630f0231bd",
- "9504b5b82d97a264d8b3735e0568decabc4b6ca275bc53cbadfc1c40",
- "03426f80e477603b10dee670939623e3da91a94267fc4e51726009ed",
- "81d3ac609f9575d742028dd496450a58a60eea2dcf8b9842994916e1",
- "96a8c5f382c992e8f30ccce9af120b067ec1d74678fa8445232f75a5",
- false,
- },
- {
- "96b2b6536f6df29be8567a72528aceeaccbaa66c66c534f3868ca9778b02faadb182e4ed34662e73b9d52ecbe9dc8e875fc05033c493108b380689ebf47e5b062e6a0cdb3dd34ce5fe347d92768d72f7b9b377c20aea927043b509c078ed2467d7113405d2ddd458811e6faf41c403a2a239240180f1430a6f4330df5d77de37",
- "851e3100368a22478a0029353045ae40d1d8202ef4d6533cfdddafd8",
- "205302ac69457dd345e86465afa72ee8c74ca97e2b0b999aec1f10c2",
- "4450c2d38b697e990721aa2dbb56578d32b4f5aeb3b9072baa955ee0",
- "e26d4b589166f7b4ba4b1c8fce823fa47aad22f8c9c396b8c6526e12",
- false,
- },
- {
- "86778dbb4a068a01047a8d245d632f636c11d2ad350740b36fad90428b454ad0f120cb558d12ea5c8a23db595d87543d06d1ef489263d01ee529871eb68737efdb8ff85bc7787b61514bed85b7e01d6be209e0a4eb0db5c8df58a5c5bf706d76cb2bdf7800208639e05b89517155d11688236e6a47ed37d8e5a2b1e0adea338e",
- "ad5bda09d319a717c1721acd6688d17020b31b47eef1edea57ceeffc",
- "c8ce98e181770a7c9418c73c63d01494b8b80a41098c5ea50692c984",
- "de5558c257ab4134e52c19d8db3b224a1899cbd08cc508ce8721d5e9",
- "745db7af5a477e5046705c0a5eff1f52cb94a79d481f0c5a5e108ecd",
- true,
- },
- {
- "4bc6ef1958556686dab1e39c3700054a304cbd8f5928603dcd97fafd1f29e69394679b638f71c9344ce6a535d104803d22119f57b5f9477e253817a52afa9bfbc9811d6cc8c8be6b6566c6ef48b439bbb532abe30627548c598867f3861ba0b154dc1c3deca06eb28df8efd28258554b5179883a36fbb1eecf4f93ee19d41e3d",
- "cc5eea2edf964018bdc0504a3793e4d2145142caa09a72ac5fb8d3e8",
- "a48d78ae5d08aa725342773975a00d4219cf7a8029bb8cf3c17c374a",
- "67b861344b4e416d4094472faf4272f6d54a497177fbc5f9ef292836",
- "1d54f3fcdad795bf3b23408ecbac3e1321d1d66f2e4e3d05f41f7020",
- false,
- },
- {
- "bb658732acbf3147729959eb7318a2058308b2739ec58907dd5b11cfa3ecf69a1752b7b7d806fe00ec402d18f96039f0b78dbb90a59c4414fb33f1f4e02e4089de4122cd93df5263a95be4d7084e2126493892816e6a5b4ed123cb705bf930c8f67af0fb4514d5769232a9b008a803af225160ce63f675bd4872c4c97b146e5e",
- "6234c936e27bf141fc7534bfc0a7eedc657f91308203f1dcbd642855",
- "27983d87ca785ef4892c3591ef4a944b1deb125dd58bd351034a6f84",
- "e94e05b42d01d0b965ffdd6c3a97a36a771e8ea71003de76c4ecb13f",
- "1dc6464ffeefbd7872a081a5926e9fc3e66d123f1784340ba17737e9",
- false,
- },
- {
- "7c00be9123bfa2c4290be1d8bc2942c7f897d9a5b7917e3aabd97ef1aab890f148400a89abd554d19bec9d8ed911ce57b22fbcf6d30ca2115f13ce0a3f569a23bad39ee645f624c49c60dcfc11e7d2be24de9c905596d8f23624d63dc46591d1f740e46f982bfae453f107e80db23545782be23ce43708245896fc54e1ee5c43",
- "9f3f037282aaf14d4772edffff331bbdda845c3f65780498cde334f1",
- "8308ee5a16e3bcb721b6bc30000a0419bc1aaedd761be7f658334066",
- "6381d7804a8808e3c17901e4d283b89449096a8fba993388fa11dc54",
- "8e858f6b5b253686a86b757bad23658cda53115ac565abca4e3d9f57",
- false,
- },
- {
- "cffc122a44840dc705bb37130069921be313d8bde0b66201aebc48add028ca131914ef2e705d6bedd19dc6cf9459bbb0f27cdfe3c50483808ffcdaffbeaa5f062e097180f07a40ef4ab6ed03fe07ed6bcfb8afeb42c97eafa2e8a8df469de07317c5e1494c41547478eff4d8c7d9f0f484ad90fedf6e1c35ee68fa73f1691601",
- "a03b88a10d930002c7b17ca6af2fd3e88fa000edf787dc594f8d4fd4",
- "e0cf7acd6ddc758e64847fe4df9915ebda2f67cdd5ec979aa57421f5",
- "387b84dcf37dc343c7d2c5beb82f0bf8bd894b395a7b894565d296c1",
- "4adc12ce7d20a89ce3925e10491c731b15ddb3f339610857a21b53b4",
- false,
- },
- {
- "26e0e0cafd85b43d16255908ccfd1f061c680df75aba3081246b337495783052ba06c60f4a486c1591a4048bae11b4d7fec4f161d80bdc9a7b79d23e44433ed625eab280521a37f23dd3e1bdc5c6a6cfaa026f3c45cf703e76dab57add93fe844dd4cda67dc3bddd01f9152579e49df60969b10f09ce9372fdd806b0c7301866",
- "9a8983c42f2b5a87c37a00458b5970320d247f0c8a88536440173f7d",
- "15e489ec6355351361900299088cfe8359f04fe0cab78dde952be80c",
- "929a21baa173d438ec9f28d6a585a2f9abcfc0a4300898668e476dc0",
- "59a853f046da8318de77ff43f26fe95a92ee296fa3f7e56ce086c872",
- true,
- },
- {
- "1078eac124f48ae4f807e946971d0de3db3748dd349b14cca5c942560fb25401b2252744f18ad5e455d2d97ed5ae745f55ff509c6c8e64606afe17809affa855c4c4cdcaf6b69ab4846aa5624ed0687541aee6f2224d929685736c6a23906d974d3c257abce1a3fb8db5951b89ecb0cda92b5207d93f6618fd0f893c32cf6a6e",
- "d6e55820bb62c2be97650302d59d667a411956138306bd566e5c3c2b",
- "631ab0d64eaf28a71b9cbd27a7a88682a2167cee6251c44e3810894f",
- "65af72bc7721eb71c2298a0eb4eed3cec96a737cc49125706308b129",
- "bd5a987c78e2d51598dbd9c34a9035b0069c580edefdacee17ad892a",
- false,
- },
- {
- "919deb1fdd831c23481dfdb2475dcbe325b04c34f82561ced3d2df0b3d749b36e255c4928973769d46de8b95f162b53cd666cad9ae145e7fcfba97919f703d864efc11eac5f260a5d920d780c52899e5d76f8fe66936ff82130761231f536e6a3d59792f784902c469aa897aabf9a0678f93446610d56d5e0981e4c8a563556b",
- "269b455b1024eb92d860a420f143ac1286b8cce43031562ae7664574",
- "baeb6ca274a77c44a0247e5eb12ca72bdd9a698b3f3ae69c9f1aaa57",
- "cb4ec2160f04613eb0dfe4608486091a25eb12aa4dec1afe91cfb008",
- "40b01d8cd06589481574f958b98ca08ade9d2a8fe31024375c01bb40",
- false,
- },
- {
- "6e012361250dacf6166d2dd1aa7be544c3206a9d43464b3fcd90f3f8cf48d08ec099b59ba6fe7d9bdcfaf244120aed1695d8be32d1b1cd6f143982ab945d635fb48a7c76831c0460851a3d62b7209c30cd9c2abdbe3d2a5282a9fcde1a6f418dd23c409bc351896b9b34d7d3a1a63bbaf3d677e612d4a80fa14829386a64b33f",
- "6d2d695efc6b43b13c14111f2109608f1020e3e03b5e21cfdbc82fcd",
- "26a4859296b7e360b69cf40be7bd97ceaffa3d07743c8489fc47ca1b",
- "9a8cb5f2fdc288b7183c5b32d8e546fc2ed1ca4285eeae00c8b572ad",
- "8c623f357b5d0057b10cdb1a1593dab57cda7bdec9cf868157a79b97",
- true,
- },
- {
- "bf6bd7356a52b234fe24d25557200971fc803836f6fec3cade9642b13a8e7af10ab48b749de76aada9d8927f9b12f75a2c383ca7358e2566c4bb4f156fce1fd4e87ef8c8d2b6b1bdd351460feb22cdca0437ac10ca5e0abbbce9834483af20e4835386f8b1c96daaa41554ceee56730aac04f23a5c765812efa746051f396566",
- "14250131b2599939cf2d6bc491be80ddfe7ad9de644387ee67de2d40",
- "b5dc473b5d014cd504022043c475d3f93c319a8bdcb7262d9e741803",
- "4f21642f2201278a95339a80f75cc91f8321fcb3c9462562f6cbf145",
- "452a5f816ea1f75dee4fd514fa91a0d6a43622981966c59a1b371ff8",
- false,
- },
- {
- "0eb7f4032f90f0bd3cf9473d6d9525d264d14c031a10acd31a053443ed5fe919d5ac35e0be77813071b4062f0b5fdf58ad5f637b76b0b305aec18f82441b6e607b44cdf6e0e3c7c57f24e6fd565e39430af4a6b1d979821ed0175fa03e3125506847654d7e1ae904ce1190ae38dc5919e257bdac2db142a6e7cd4da6c2e83770",
- "d1f342b7790a1667370a1840255ac5bbbdc66f0bc00ae977d99260ac",
- "76416cabae2de9a1000b4646338b774baabfa3db4673790771220cdb",
- "bc85e3fc143d19a7271b2f9e1c04b86146073f3fab4dda1c3b1f35ca",
- "9a5c70ede3c48d5f43307a0c2a4871934424a3303b815df4bb0f128e",
- false,
- },
- {
- "5cc25348a05d85e56d4b03cec450128727bc537c66ec3a9fb613c151033b5e86878632249cba83adcefc6c1e35dcd31702929c3b57871cda5c18d1cf8f9650a25b917efaed56032e43b6fc398509f0d2997306d8f26675f3a8683b79ce17128e006aa0903b39eeb2f1001be65de0520115e6f919de902b32c38d691a69c58c92",
- "7e49a7abf16a792e4c7bbc4d251820a2abd22d9f2fc252a7bf59c9a6",
- "44236a8fb4791c228c26637c28ae59503a2f450d4cfb0dc42aa843b9",
- "084461b4050285a1a85b2113be76a17878d849e6bc489f4d84f15cd8",
- "079b5bddcc4d45de8dbdfd39f69817c7e5afa454a894d03ee1eaaac3",
- false,
- },
- {
- "1951533ce33afb58935e39e363d8497a8dd0442018fd96dff167b3b23d7206a3ee182a3194765df4768a3284e23b8696c199b4686e670d60c9d782f08794a4bccc05cffffbd1a12acd9eb1cfa01f7ebe124da66ecff4599ea7720c3be4bb7285daa1a86ebf53b042bd23208d468c1b3aa87381f8e1ad63e2b4c2ba5efcf05845",
- "31945d12ebaf4d81f02be2b1768ed80784bf35cf5e2ff53438c11493",
- "a62bebffac987e3b9d3ec451eb64c462cdf7b4aa0b1bbb131ceaa0a4",
- "bc3c32b19e42b710bca5c6aaa128564da3ddb2726b25f33603d2af3c",
- "ed1a719cc0c507edc5239d76fe50e2306c145ad252bd481da04180c0",
- false,
- },
-}
-
func TestVectors(t *testing.T) {
- sha := sha1.New()
+ // This test runs the full set of NIST test vectors from
+ // http://csrc.nist.gov/groups/STM/cavp/documents/dss/186-3ecdsatestvectors.zip
+ //
+ // The SigVer.rsp file has been edited to remove test vectors for
+ // unsupported algorithms and has been compressed.
+
+ if testing.Short() {
+ return
+ }
+
+ f, err := os.Open("testdata/SigVer.rsp.bz2")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ buf := bufio.NewReader(bzip2.NewReader(f))
+
+ lineNo := 1
+ var h hash.Hash
+ var msg []byte
+ var hashed []byte
+ var r, s *big.Int
+ pub := new(PublicKey)
- for i, test := range testVectors {
- pub := PublicKey{
- Curve: elliptic.P224(),
- X: fromHex(test.Qx),
- Y: fromHex(test.Qy),
+ for {
+ line, err := buf.ReadString('\n')
+ if len(line) == 0 {
+ if err == io.EOF {
+ break
+ }
+ t.Fatalf("error reading from input: %s", err)
}
- msg, _ := hex.DecodeString(test.msg)
- sha.Reset()
- sha.Write(msg)
- hashed := sha.Sum(nil)
- r := fromHex(test.r)
- s := fromHex(test.s)
- if Verify(&pub, hashed, r, s) != test.ok {
- t.Errorf("%d: bad result", i)
+ lineNo++
+ // Need to remove \r\n from the end of the line.
+ if !strings.HasSuffix(line, "\r\n") {
+ t.Fatalf("bad line ending (expected \\r\\n) on line %d", lineNo)
}
- if testing.Short() {
- break
+ line = line[:len(line)-2]
+
+ if len(line) == 0 || line[0] == '#' {
+ continue
+ }
+
+ if line[0] == '[' {
+ line = line[1 : len(line)-1]
+ parts := strings.SplitN(line, ",", 2)
+
+ switch parts[0] {
+ case "P-224":
+ pub.Curve = elliptic.P224()
+ case "P-256":
+ pub.Curve = elliptic.P256()
+ case "P-384":
+ pub.Curve = elliptic.P384()
+ case "P-521":
+ pub.Curve = elliptic.P521()
+ default:
+ pub.Curve = nil
+ }
+
+ switch parts[1] {
+ case "SHA-1":
+ h = sha1.New()
+ case "SHA-224":
+ h = sha256.New224()
+ case "SHA-256":
+ h = sha256.New()
+ case "SHA-384":
+ h = sha512.New384()
+ case "SHA-512":
+ h = sha512.New()
+ default:
+ h = nil
+ }
+
+ continue
+ }
+
+ if h == nil || pub.Curve == nil {
+ continue
+ }
+
+ switch {
+ case strings.HasPrefix(line, "Msg = "):
+ if msg, err = hex.DecodeString(line[6:]); err != nil {
+ t.Fatalf("failed to decode message on line %d: %s", lineNo, err)
+ }
+ case strings.HasPrefix(line, "Qx = "):
+ pub.X = fromHex(line[5:])
+ case strings.HasPrefix(line, "Qy = "):
+ pub.Y = fromHex(line[5:])
+ case strings.HasPrefix(line, "R = "):
+ r = fromHex(line[4:])
+ case strings.HasPrefix(line, "S = "):
+ s = fromHex(line[4:])
+ case strings.HasPrefix(line, "Result = "):
+ expected := line[9] == 'P'
+ h.Reset()
+ h.Write(msg)
+ hashed := h.Sum(hashed[:0])
+ if Verify(pub, hashed, r, s) != expected {
+ t.Fatalf("incorrect result on line %d", lineNo)
+ }
+ default:
+ t.Fatalf("unknown variable on line %d: %s", lineNo, line)
}
}
}
diff --git a/src/pkg/crypto/ecdsa/testdata/SigVer.rsp.bz2 b/src/pkg/crypto/ecdsa/testdata/SigVer.rsp.bz2
new file mode 100644
index 000000000..09fe2b427
--- /dev/null
+++ b/src/pkg/crypto/ecdsa/testdata/SigVer.rsp.bz2
Binary files differ
diff --git a/src/pkg/crypto/elliptic/elliptic.go b/src/pkg/crypto/elliptic/elliptic.go
index 30835a90b..7a4ff6614 100644
--- a/src/pkg/crypto/elliptic/elliptic.go
+++ b/src/pkg/crypto/elliptic/elliptic.go
@@ -31,10 +31,10 @@ type Curve interface {
// Double returns 2*(x,y)
Double(x1, y1 *big.Int) (x, y *big.Int)
// ScalarMult returns k*(Bx,By) where k is a number in big-endian form.
- ScalarMult(x1, y1 *big.Int, scalar []byte) (x, y *big.Int)
- // ScalarBaseMult returns k*G, where G is the base point of the group and k
- // is an integer in big-endian form.
- ScalarBaseMult(scalar []byte) (x, y *big.Int)
+ ScalarMult(x1, y1 *big.Int, k []byte) (x, y *big.Int)
+ // ScalarBaseMult returns k*G, where G is the base point of the group
+ // and k is an integer in big-endian form.
+ ScalarBaseMult(k []byte) (x, y *big.Int)
}
// CurveParams contains the parameters of an elliptic curve and also provides
@@ -69,9 +69,24 @@ func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool {
return x3.Cmp(y2) == 0
}
+// zForAffine returns a Jacobian Z value for the affine point (x, y). If x and
+// y are zero, it assumes that they represent the point at infinity because (0,
+// 0) is not on the any of the curves handled here.
+func zForAffine(x, y *big.Int) *big.Int {
+ z := new(big.Int)
+ if x.Sign() != 0 || y.Sign() != 0 {
+ z.SetInt64(1)
+ }
+ return z
+}
+
// affineFromJacobian reverses the Jacobian transform. See the comment at the
-// top of the file.
+// top of the file. If the point is ∞ it returns 0, 0.
func (curve *CurveParams) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) {
+ if z.Sign() == 0 {
+ return new(big.Int), new(big.Int)
+ }
+
zinv := new(big.Int).ModInverse(z, curve.P)
zinvsq := new(big.Int).Mul(zinv, zinv)
@@ -84,14 +99,29 @@ func (curve *CurveParams) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.
}
func (curve *CurveParams) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
- z := new(big.Int).SetInt64(1)
- return curve.affineFromJacobian(curve.addJacobian(x1, y1, z, x2, y2, z))
+ z1 := zForAffine(x1, y1)
+ z2 := zForAffine(x2, y2)
+ return curve.affineFromJacobian(curve.addJacobian(x1, y1, z1, x2, y2, z2))
}
// addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and
// (x2, y2, z2) and returns their sum, also in Jacobian form.
func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) {
// See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl
+ x3, y3, z3 := new(big.Int), new(big.Int), new(big.Int)
+ if z1.Sign() == 0 {
+ x3.Set(x2)
+ y3.Set(y2)
+ z3.Set(z2)
+ return x3, y3, z3
+ }
+ if z2.Sign() == 0 {
+ x3.Set(x1)
+ y3.Set(y1)
+ z3.Set(z1)
+ return x3, y3, z3
+ }
+
z1z1 := new(big.Int).Mul(z1, z1)
z1z1.Mod(z1z1, curve.P)
z2z2 := new(big.Int).Mul(z2, z2)
@@ -102,6 +132,7 @@ func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int
u2 := new(big.Int).Mul(x2, z1z1)
u2.Mod(u2, curve.P)
h := new(big.Int).Sub(u2, u1)
+ xEqual := h.Sign() == 0
if h.Sign() == -1 {
h.Add(h, curve.P)
}
@@ -119,17 +150,21 @@ func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int
if r.Sign() == -1 {
r.Add(r, curve.P)
}
+ yEqual := r.Sign() == 0
+ if xEqual && yEqual {
+ return curve.doubleJacobian(x1, y1, z1)
+ }
r.Lsh(r, 1)
v := new(big.Int).Mul(u1, i)
- x3 := new(big.Int).Set(r)
+ x3.Set(r)
x3.Mul(x3, x3)
x3.Sub(x3, j)
x3.Sub(x3, v)
x3.Sub(x3, v)
x3.Mod(x3, curve.P)
- y3 := new(big.Int).Set(r)
+ y3.Set(r)
v.Sub(v, x3)
y3.Mul(y3, v)
s1.Mul(s1, j)
@@ -137,16 +172,10 @@ func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int
y3.Sub(y3, s1)
y3.Mod(y3, curve.P)
- z3 := new(big.Int).Add(z1, z2)
+ z3.Add(z1, z2)
z3.Mul(z3, z3)
z3.Sub(z3, z1z1)
- if z3.Sign() == -1 {
- z3.Add(z3, curve.P)
- }
z3.Sub(z3, z2z2)
- if z3.Sign() == -1 {
- z3.Add(z3, curve.P)
- }
z3.Mul(z3, h)
z3.Mod(z3, curve.P)
@@ -154,7 +183,7 @@ func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int
}
func (curve *CurveParams) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
- z1 := new(big.Int).SetInt64(1)
+ z1 := zForAffine(x1, y1)
return curve.affineFromJacobian(curve.doubleJacobian(x1, y1, z1))
}
@@ -219,40 +248,19 @@ func (curve *CurveParams) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int,
}
func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) {
- // We have a slight problem in that the identity of the group (the
- // point at infinity) cannot be represented in (x, y) form on a finite
- // machine. Thus the standard add/double algorithm has to be tweaked
- // slightly: our initial state is not the identity, but x, and we
- // ignore the first true bit in |k|. If we don't find any true bits in
- // |k|, then we return nil, nil, because we cannot return the identity
- // element.
-
Bz := new(big.Int).SetInt64(1)
- x := Bx
- y := By
- z := Bz
+ x, y, z := new(big.Int), new(big.Int), new(big.Int)
- seenFirstTrue := false
for _, byte := range k {
for bitNum := 0; bitNum < 8; bitNum++ {
- if seenFirstTrue {
- x, y, z = curve.doubleJacobian(x, y, z)
- }
+ x, y, z = curve.doubleJacobian(x, y, z)
if byte&0x80 == 0x80 {
- if !seenFirstTrue {
- seenFirstTrue = true
- } else {
- x, y, z = curve.addJacobian(Bx, By, Bz, x, y, z)
- }
+ x, y, z = curve.addJacobian(Bx, By, Bz, x, y, z)
}
byte <<= 1
}
}
- if !seenFirstTrue {
- return nil, nil
- }
-
return curve.affineFromJacobian(x, y, z)
}
@@ -370,7 +378,7 @@ func P384() Curve {
return p384
}
-// P256 returns a Curve which implements P-521 (see FIPS 186-3, section D.2.5)
+// P521 returns a Curve which implements P-521 (see FIPS 186-3, section D.2.5)
func P521() Curve {
initonce.Do(initAll)
return p521
diff --git a/src/pkg/crypto/elliptic/elliptic_test.go b/src/pkg/crypto/elliptic/elliptic_test.go
index 1e3407ee0..58f903966 100644
--- a/src/pkg/crypto/elliptic/elliptic_test.go
+++ b/src/pkg/crypto/elliptic/elliptic_test.go
@@ -322,6 +322,44 @@ func TestGenericBaseMult(t *testing.T) {
}
}
+func TestInfinity(t *testing.T) {
+ tests := []struct {
+ name string
+ curve Curve
+ }{
+ {"p224", P224()},
+ {"p256", P256()},
+ }
+
+ for _, test := range tests {
+ curve := test.curve
+ x, y := curve.ScalarBaseMult(nil)
+ if x.Sign() != 0 || y.Sign() != 0 {
+ t.Errorf("%s: x^0 != ∞", test.name)
+ }
+ x.SetInt64(0)
+ y.SetInt64(0)
+
+ x2, y2 := curve.Double(x, y)
+ if x2.Sign() != 0 || y2.Sign() != 0 {
+ t.Errorf("%s: 2∞ != ∞", test.name)
+ }
+
+ baseX := curve.Params().Gx
+ baseY := curve.Params().Gy
+
+ x3, y3 := curve.Add(baseX, baseY, x, y)
+ if x3.Cmp(baseX) != 0 || y3.Cmp(baseY) != 0 {
+ t.Errorf("%s: x+∞ != x", test.name)
+ }
+
+ x4, y4 := curve.Add(x, y, baseX, baseY)
+ if x4.Cmp(baseX) != 0 || y4.Cmp(baseY) != 0 {
+ t.Errorf("%s: ∞+x != x", test.name)
+ }
+ }
+}
+
func BenchmarkBaseMult(b *testing.B) {
b.ResetTimer()
p224 := P224()
diff --git a/src/pkg/crypto/elliptic/p224.go b/src/pkg/crypto/elliptic/p224.go
index 17571c252..1f7ff3f9d 100644
--- a/src/pkg/crypto/elliptic/p224.go
+++ b/src/pkg/crypto/elliptic/p224.go
@@ -80,10 +80,14 @@ func (p224Curve) Add(bigX1, bigY1, bigX2, bigY2 *big.Int) (x, y *big.Int) {
p224FromBig(&x1, bigX1)
p224FromBig(&y1, bigY1)
- z1[0] = 1
+ if bigX1.Sign() != 0 || bigY1.Sign() != 0 {
+ z1[0] = 1
+ }
p224FromBig(&x2, bigX2)
p224FromBig(&y2, bigY2)
- z2[0] = 1
+ if bigX2.Sign() != 0 || bigY2.Sign() != 0 {
+ z2[0] = 1
+ }
p224AddJacobian(&x3, &y3, &z3, &x1, &y1, &z1, &x2, &y2, &z2)
return p224ToAffine(&x3, &y3, &z3)
@@ -132,6 +136,44 @@ func (curve p224Curve) ScalarBaseMult(scalar []byte) (x, y *big.Int) {
// exactly, making the reflections during a reduce much nicer.
type p224FieldElement [8]uint32
+// p224P is the order of the field, represented as a p224FieldElement.
+var p224P = [8]uint32{1, 0, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff}
+
+// p224IsZero returns 1 if a == 0 mod p and 0 otherwise.
+//
+// a[i] < 2**29
+func p224IsZero(a *p224FieldElement) uint32 {
+ // Since a p224FieldElement contains 224 bits there are two possible
+ // representations of 0: 0 and p.
+ var minimal p224FieldElement
+ p224Contract(&minimal, a)
+
+ var isZero, isP uint32
+ for i, v := range minimal {
+ isZero |= v
+ isP |= v - p224P[i]
+ }
+
+ // If either isZero or isP is 0, then we should return 1.
+ isZero |= isZero >> 16
+ isZero |= isZero >> 8
+ isZero |= isZero >> 4
+ isZero |= isZero >> 2
+ isZero |= isZero >> 1
+
+ isP |= isP >> 16
+ isP |= isP >> 8
+ isP |= isP >> 4
+ isP |= isP >> 2
+ isP |= isP >> 1
+
+ // For isZero and isP, the LSB is 0 iff all the bits are zero.
+ result := isZero & isP
+ result = (^result) & 1
+
+ return result
+}
+
// p224Add computes *out = a+b
//
// a[i] + b[i] < 2**32
@@ -406,7 +448,7 @@ func p224Contract(out, in *p224FieldElement) {
// true.
top4AllOnes := uint32(0xffffffff)
for i := 4; i < 8; i++ {
- top4AllOnes &= (out[i] & bottom28Bits) - 1
+ top4AllOnes &= out[i]
}
top4AllOnes |= 0xf0000000
// Now we replicate any zero bits to all the bits in top4AllOnes.
@@ -441,7 +483,7 @@ func p224Contract(out, in *p224FieldElement) {
out3Equal = ^uint32(int32(out3Equal<<31) >> 31)
// If out[3] > 0xffff000 then n's MSB will be zero.
- out3GT := ^uint32(int32(n<<31) >> 31)
+ out3GT := ^uint32(int32(n) >> 31)
mask := top4AllOnes & ((out3Equal & bottom3NonZero) | out3GT)
out[0] -= 1 & mask
@@ -463,6 +505,9 @@ func p224AddJacobian(x3, y3, z3, x1, y1, z1, x2, y2, z2 *p224FieldElement) {
var z1z1, z2z2, u1, u2, s1, s2, h, i, j, r, v p224FieldElement
var c p224LargeFieldElement
+ z1IsZero := p224IsZero(z1)
+ z2IsZero := p224IsZero(z2)
+
// Z1Z1 = Z1²
p224Square(&z1z1, z1, &c)
// Z2Z2 = Z2²
@@ -480,6 +525,7 @@ func p224AddJacobian(x3, y3, z3, x1, y1, z1, x2, y2, z2 *p224FieldElement) {
// H = U2-U1
p224Sub(&h, &u2, &u1)
p224Reduce(&h)
+ xEqual := p224IsZero(&h)
// I = (2*H)²
for j := 0; j < 8; j++ {
i[j] = h[j] << 1
@@ -491,6 +537,11 @@ func p224AddJacobian(x3, y3, z3, x1, y1, z1, x2, y2, z2 *p224FieldElement) {
// r = 2*(S2-S1)
p224Sub(&r, &s2, &s1)
p224Reduce(&r)
+ yEqual := p224IsZero(&r)
+ if xEqual == 1 && yEqual == 1 && z1IsZero == 0 && z2IsZero == 0 {
+ p224DoubleJacobian(x3, y3, z3, x1, y1, z1)
+ return
+ }
for i := 0; i < 8; i++ {
r[i] <<= 1
}
@@ -524,6 +575,13 @@ func p224AddJacobian(x3, y3, z3, x1, y1, z1, x2, y2, z2 *p224FieldElement) {
p224Mul(&z1z1, &z1z1, &r, &c)
p224Sub(y3, &z1z1, &s1)
p224Reduce(y3)
+
+ p224CopyConditional(x3, x2, z1IsZero)
+ p224CopyConditional(x3, x1, z2IsZero)
+ p224CopyConditional(y3, y2, z1IsZero)
+ p224CopyConditional(y3, y1, z2IsZero)
+ p224CopyConditional(z3, z2, z1IsZero)
+ p224CopyConditional(z3, z1, z2IsZero)
}
// p224DoubleJacobian computes *out = a+a.
@@ -593,22 +651,19 @@ func p224CopyConditional(out, in *p224FieldElement, control uint32) {
func p224ScalarMult(outX, outY, outZ, inX, inY, inZ *p224FieldElement, scalar []byte) {
var xx, yy, zz p224FieldElement
for i := 0; i < 8; i++ {
+ outX[i] = 0
+ outY[i] = 0
outZ[i] = 0
}
- firstBit := uint32(1)
for _, byte := range scalar {
for bitNum := uint(0); bitNum < 8; bitNum++ {
p224DoubleJacobian(outX, outY, outZ, outX, outY, outZ)
bit := uint32((byte >> (7 - bitNum)) & 1)
p224AddJacobian(&xx, &yy, &zz, inX, inY, inZ, outX, outY, outZ)
- p224CopyConditional(outX, inX, firstBit&bit)
- p224CopyConditional(outY, inY, firstBit&bit)
- p224CopyConditional(outZ, inZ, firstBit&bit)
- p224CopyConditional(outX, &xx, ^firstBit&bit)
- p224CopyConditional(outY, &yy, ^firstBit&bit)
- p224CopyConditional(outZ, &zz, ^firstBit&bit)
- firstBit = firstBit & ^bit
+ p224CopyConditional(outX, &xx, bit)
+ p224CopyConditional(outY, &yy, bit)
+ p224CopyConditional(outZ, &zz, bit)
}
}
}
@@ -618,16 +673,8 @@ func p224ToAffine(x, y, z *p224FieldElement) (*big.Int, *big.Int) {
var zinv, zinvsq, outx, outy p224FieldElement
var tmp p224LargeFieldElement
- isPointAtInfinity := true
- for i := 0; i < 8; i++ {
- if z[i] != 0 {
- isPointAtInfinity = false
- break
- }
- }
-
- if isPointAtInfinity {
- return nil, nil
+ if isPointAtInfinity := p224IsZero(z); isPointAtInfinity == 1 {
+ return new(big.Int), new(big.Int)
}
p224Invert(&zinv, z)
diff --git a/src/pkg/crypto/hmac/hmac.go b/src/pkg/crypto/hmac/hmac.go
index a97ce0972..b6f4919a7 100644
--- a/src/pkg/crypto/hmac/hmac.go
+++ b/src/pkg/crypto/hmac/hmac.go
@@ -2,13 +2,27 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Package hmac implements the Keyed-Hash Message Authentication Code (HMAC) as
-// defined in U.S. Federal Information Processing Standards Publication 198.
-// An HMAC is a cryptographic hash that uses a key to sign a message.
-// The receiver verifies the hash by recomputing it using the same key.
+/*
+Package hmac implements the Keyed-Hash Message Authentication Code (HMAC) as
+defined in U.S. Federal Information Processing Standards Publication 198.
+An HMAC is a cryptographic hash that uses a key to sign a message.
+The receiver verifies the hash by recomputing it using the same key.
+
+Receivers should be careful to use Equal to compare MACs in order to avoid
+timing side-channels:
+
+ // CheckMAC returns true if messageMAC is a valid HMAC tag for message.
+ func CheckMAC(message, messageMAC, key []byte) bool {
+ mac := hmac.New(sha256.New, key)
+ mac.Write(message)
+ expectedMAC := mac.Sum(nil)
+ return hmac.Equal(messageMAC, expectedMAC)
+ }
+*/
package hmac
import (
+ "crypto/subtle"
"hash"
)
@@ -57,7 +71,7 @@ func (h *hmac) BlockSize() int { return h.blocksize }
func (h *hmac) Reset() {
h.inner.Reset()
h.tmpPad(0x36)
- h.inner.Write(h.tmp[0:h.blocksize])
+ h.inner.Write(h.tmp[:h.blocksize])
}
// New returns a new HMAC hash using the given hash.Hash type and key.
@@ -78,3 +92,11 @@ func New(h func() hash.Hash, key []byte) hash.Hash {
hm.Reset()
return hm
}
+
+// Equal compares two MACs for equality without leaking timing information.
+func Equal(mac1, mac2 []byte) bool {
+ // We don't have to be constant time if the lengths of the MACs are
+ // different as that suggests that a completely different hash function
+ // was used.
+ return len(mac1) == len(mac2) && subtle.ConstantTimeCompare(mac1, mac2) == 1
+}
diff --git a/src/pkg/crypto/hmac/hmac_test.go b/src/pkg/crypto/hmac/hmac_test.go
index 07957414c..d4860424e 100644
--- a/src/pkg/crypto/hmac/hmac_test.go
+++ b/src/pkg/crypto/hmac/hmac_test.go
@@ -491,3 +491,22 @@ func TestHMAC(t *testing.T) {
}
}
}
+
+func TestEqual(t *testing.T) {
+ a := []byte("test")
+ b := []byte("test1")
+ c := []byte("test2")
+
+ if !Equal(b, b) {
+ t.Error("Equal failed with equal arguments")
+ }
+ if Equal(a, b) {
+ t.Error("Equal accepted a prefix of the second argument")
+ }
+ if Equal(b, a) {
+ t.Error("Equal accepted a prefix of the first argument")
+ }
+ if Equal(b, c) {
+ t.Error("Equal accepted unequal slices")
+ }
+}
diff --git a/src/pkg/crypto/md5/gen.go b/src/pkg/crypto/md5/gen.go
new file mode 100644
index 000000000..966bdae26
--- /dev/null
+++ b/src/pkg/crypto/md5/gen.go
@@ -0,0 +1,300 @@
+// 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 ignore
+
+// This program generates md5block.go
+// Invoke as
+//
+// go run gen.go [-full] |gofmt >md5block.go
+//
+// The -full flag causes the generated code to do a full
+// (16x) unrolling instead of a 4x unrolling.
+
+package main
+
+import (
+ "flag"
+ "log"
+ "os"
+ "strings"
+ "text/template"
+)
+
+func main() {
+ flag.Parse()
+
+ t := template.Must(template.New("main").Funcs(funcs).Parse(program))
+ if err := t.Execute(os.Stdout, data); err != nil {
+ log.Fatal(err)
+ }
+}
+
+type Data struct {
+ a, b, c, d string
+ Shift1 []int
+ Shift2 []int
+ Shift3 []int
+ Shift4 []int
+ Table1 []uint32
+ Table2 []uint32
+ Table3 []uint32
+ Table4 []uint32
+ Full bool
+}
+
+var funcs = template.FuncMap{
+ "dup": dup,
+ "relabel": relabel,
+ "rotate": rotate,
+}
+
+func dup(count int, x []int) []int {
+ var out []int
+ for i := 0; i < count; i++ {
+ out = append(out, x...)
+ }
+ return out
+}
+
+func relabel(s string) string {
+ return strings.NewReplacer("a", data.a, "b", data.b, "c", data.c, "d", data.d).Replace(s)
+}
+
+func rotate() string {
+ data.a, data.b, data.c, data.d = data.d, data.a, data.b, data.c
+ return "" // no output
+}
+
+func init() {
+ flag.BoolVar(&data.Full, "full", false, "complete unrolling")
+}
+
+var data = Data{
+ a: "a",
+ b: "b",
+ c: "c",
+ d: "d",
+ Shift1: []int{7, 12, 17, 22},
+ Shift2: []int{5, 9, 14, 20},
+ Shift3: []int{4, 11, 16, 23},
+ Shift4: []int{6, 10, 15, 21},
+
+ // table[i] = int((1<<32) * abs(sin(i+1 radians))).
+ Table1: []uint32{
+ // round 1
+ 0xd76aa478,
+ 0xe8c7b756,
+ 0x242070db,
+ 0xc1bdceee,
+ 0xf57c0faf,
+ 0x4787c62a,
+ 0xa8304613,
+ 0xfd469501,
+ 0x698098d8,
+ 0x8b44f7af,
+ 0xffff5bb1,
+ 0x895cd7be,
+ 0x6b901122,
+ 0xfd987193,
+ 0xa679438e,
+ 0x49b40821,
+ },
+ Table2: []uint32{
+ // round 2
+ 0xf61e2562,
+ 0xc040b340,
+ 0x265e5a51,
+ 0xe9b6c7aa,
+ 0xd62f105d,
+ 0x2441453,
+ 0xd8a1e681,
+ 0xe7d3fbc8,
+ 0x21e1cde6,
+ 0xc33707d6,
+ 0xf4d50d87,
+ 0x455a14ed,
+ 0xa9e3e905,
+ 0xfcefa3f8,
+ 0x676f02d9,
+ 0x8d2a4c8a,
+ },
+ Table3: []uint32{
+ // round3
+ 0xfffa3942,
+ 0x8771f681,
+ 0x6d9d6122,
+ 0xfde5380c,
+ 0xa4beea44,
+ 0x4bdecfa9,
+ 0xf6bb4b60,
+ 0xbebfbc70,
+ 0x289b7ec6,
+ 0xeaa127fa,
+ 0xd4ef3085,
+ 0x4881d05,
+ 0xd9d4d039,
+ 0xe6db99e5,
+ 0x1fa27cf8,
+ 0xc4ac5665,
+ },
+ Table4: []uint32{
+ // round 4
+ 0xf4292244,
+ 0x432aff97,
+ 0xab9423a7,
+ 0xfc93a039,
+ 0x655b59c3,
+ 0x8f0ccc92,
+ 0xffeff47d,
+ 0x85845dd1,
+ 0x6fa87e4f,
+ 0xfe2ce6e0,
+ 0xa3014314,
+ 0x4e0811a1,
+ 0xf7537e82,
+ 0xbd3af235,
+ 0x2ad7d2bb,
+ 0xeb86d391,
+ },
+}
+
+var program = `
+package md5
+
+import (
+ "unsafe"
+ "runtime"
+)
+
+{{if not .Full}}
+ var t1 = [...]uint32{
+ {{range .Table1}}{{printf "\t%#x,\n" .}}{{end}}
+ }
+
+ var t2 = [...]uint32{
+ {{range .Table2}}{{printf "\t%#x,\n" .}}{{end}}
+ }
+
+ var t3 = [...]uint32{
+ {{range .Table3}}{{printf "\t%#x,\n" .}}{{end}}
+ }
+
+ var t4 = [...]uint32{
+ {{range .Table4}}{{printf "\t%#x,\n" .}}{{end}}
+ }
+{{end}}
+
+func block(dig *digest, p []byte) {
+ a := dig.s[0]
+ b := dig.s[1]
+ c := dig.s[2]
+ d := dig.s[3]
+ var X *[16]uint32
+ var xbuf [16]uint32
+ for len(p) >= chunk {
+ aa, bb, cc, dd := a, b, c, d
+
+ // This is a constant condition - it is not evaluated on each iteration.
+ if runtime.GOARCH == "amd64" || runtime.GOARCH == "386" {
+ // MD5 was designed so that x86 processors can just iterate
+ // over the block data directly as uint32s, and we generate
+ // less code and run 1.3x faster if we take advantage of that.
+ // My apologies.
+ X = (*[16]uint32)(unsafe.Pointer(&p[0]))
+ } else if uintptr(unsafe.Pointer(&p[0]))&(unsafe.Alignof(uint32(0))-1) == 0 {
+ X = (*[16]uint32)(unsafe.Pointer(&p[0]))
+ } else {
+ X = &xbuf
+ j := 0
+ for i := 0; i < 16; i++ {
+ X[i&15] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24
+ j += 4
+ }
+ }
+
+ {{if .Full}}
+ // Round 1.
+ {{range $i, $s := dup 4 .Shift1}}
+ {{index $.Table1 $i | printf "a += (((c^d)&b)^d) + X[%d] + %d" $i | relabel}}
+ {{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+ {{rotate}}
+ {{end}}
+
+ // Round 2.
+ {{range $i, $s := dup 4 .Shift2}}
+ {{index $.Table2 $i | printf "a += (((b^c)&d)^c) + X[(1+5*%d)&15] + %d" $i | relabel}}
+ {{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+ {{rotate}}
+ {{end}}
+
+ // Round 3.
+ {{range $i, $s := dup 4 .Shift3}}
+ {{index $.Table3 $i | printf "a += (b^c^d) + X[(5+3*%d)&15] + %d" $i | relabel}}
+ {{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+ {{rotate}}
+ {{end}}
+
+ // Round 4.
+ {{range $i, $s := dup 4 .Shift4}}
+ {{index $.Table4 $i | printf "a += (c^(b|^d)) + X[(7*%d)&15] + %d" $i | relabel}}
+ {{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+ {{rotate}}
+ {{end}}
+ {{else}}
+ // Round 1.
+ for i := uint(0); i < 16; {
+ {{range $s := .Shift1}}
+ {{printf "a += (((c^d)&b)^d) + X[i&15] + t1[i&15]" | relabel}}
+ {{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+ i++
+ {{rotate}}
+ {{end}}
+ }
+
+ // Round 2.
+ for i := uint(0); i < 16; {
+ {{range $s := .Shift2}}
+ {{printf "a += (((b^c)&d)^c) + X[(1+5*i)&15] + t2[i&15]" | relabel}}
+ {{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+ i++
+ {{rotate}}
+ {{end}}
+ }
+
+ // Round 3.
+ for i := uint(0); i < 16; {
+ {{range $s := .Shift3}}
+ {{printf "a += (b^c^d) + X[(5+3*i)&15] + t3[i&15]" | relabel}}
+ {{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+ i++
+ {{rotate}}
+ {{end}}
+ }
+
+ // Round 4.
+ for i := uint(0); i < 16; {
+ {{range $s := .Shift4}}
+ {{printf "a += (c^(b|^d)) + X[(7*i)&15] + t4[i&15]" | relabel}}
+ {{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+ i++
+ {{rotate}}
+ {{end}}
+ }
+ {{end}}
+
+ a += aa
+ b += bb
+ c += cc
+ d += dd
+
+ p = p[chunk:]
+ }
+
+ dig.s[0] = a
+ dig.s[1] = b
+ dig.s[2] = c
+ dig.s[3] = d
+}
+`
diff --git a/src/pkg/crypto/md5/md5.go b/src/pkg/crypto/md5/md5.go
index cfb728c94..825e5c8a2 100644
--- a/src/pkg/crypto/md5/md5.go
+++ b/src/pkg/crypto/md5/md5.go
@@ -21,26 +21,26 @@ const Size = 16
const BlockSize = 64
const (
- _Chunk = 64
- _Init0 = 0x67452301
- _Init1 = 0xEFCDAB89
- _Init2 = 0x98BADCFE
- _Init3 = 0x10325476
+ chunk = 64
+ init0 = 0x67452301
+ init1 = 0xEFCDAB89
+ init2 = 0x98BADCFE
+ init3 = 0x10325476
)
// digest represents the partial evaluation of a checksum.
type digest struct {
s [4]uint32
- x [_Chunk]byte
+ x [chunk]byte
nx int
len uint64
}
func (d *digest) Reset() {
- d.s[0] = _Init0
- d.s[1] = _Init1
- d.s[2] = _Init2
- d.s[3] = _Init3
+ d.s[0] = init0
+ d.s[1] = init1
+ d.s[2] = init2
+ d.s[3] = init3
d.nx = 0
d.len = 0
}
@@ -61,21 +61,24 @@ func (d *digest) Write(p []byte) (nn int, err error) {
d.len += uint64(nn)
if d.nx > 0 {
n := len(p)
- if n > _Chunk-d.nx {
- n = _Chunk - d.nx
+ if n > chunk-d.nx {
+ n = chunk - d.nx
}
for i := 0; i < n; i++ {
d.x[d.nx+i] = p[i]
}
d.nx += n
- if d.nx == _Chunk {
- _Block(d, d.x[0:])
+ if d.nx == chunk {
+ block(d, d.x[0:chunk])
d.nx = 0
}
p = p[n:]
}
- n := _Block(d, p)
- p = p[n:]
+ if len(p) >= chunk {
+ n := len(p) &^ (chunk - 1)
+ block(d, p[:n])
+ p = p[n:]
+ }
if len(p) > 0 {
d.nx = copy(d.x[:], p)
}
diff --git a/src/pkg/crypto/md5/md5_test.go b/src/pkg/crypto/md5/md5_test.go
index aae875464..3ef4519b9 100644
--- a/src/pkg/crypto/md5/md5_test.go
+++ b/src/pkg/crypto/md5/md5_test.go
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package md5_test
+package md5
import (
- "crypto/md5"
"fmt"
"io"
"testing"
+ "unsafe"
)
type md5Test struct {
@@ -53,14 +53,20 @@ var golden = []md5Test{
func TestGolden(t *testing.T) {
for i := 0; i < len(golden); i++ {
g := golden[i]
- c := md5.New()
- for j := 0; j < 3; j++ {
+ c := New()
+ buf := make([]byte, len(g.in)+4)
+ for j := 0; j < 3+4; j++ {
if j < 2 {
io.WriteString(c, g.in)
- } else {
+ } else if j == 2 {
io.WriteString(c, g.in[0:len(g.in)/2])
c.Sum(nil)
io.WriteString(c, g.in[len(g.in)/2:])
+ } else if j > 2 {
+ // test unaligned write
+ buf = buf[1:]
+ copy(buf, g.in)
+ c.Write(buf[:len(g.in)])
}
s := fmt.Sprintf("%x", c.Sum(nil))
if s != g.out {
@@ -72,9 +78,53 @@ func TestGolden(t *testing.T) {
}
func ExampleNew() {
- h := md5.New()
+ h := New()
io.WriteString(h, "The fog is getting thicker!")
io.WriteString(h, "And Leon's getting laaarger!")
fmt.Printf("%x", h.Sum(nil))
// Output: e2c569be17396eca2a2e3c11578123ed
}
+
+var bench = New()
+var buf = make([]byte, 8192+1)
+var sum = make([]byte, bench.Size())
+
+func benchmarkSize(b *testing.B, size int, unaligned bool) {
+ b.SetBytes(int64(size))
+ buf := buf
+ if unaligned {
+ if uintptr(unsafe.Pointer(&buf[0]))&(unsafe.Alignof(uint32(0))-1) == 0 {
+ buf = buf[1:]
+ }
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ bench.Reset()
+ bench.Write(buf[:size])
+ bench.Sum(sum[:0])
+ }
+}
+
+func BenchmarkHash8Bytes(b *testing.B) {
+ benchmarkSize(b, 8, false)
+}
+
+func BenchmarkHash1K(b *testing.B) {
+ benchmarkSize(b, 1024, false)
+}
+
+func BenchmarkHash8K(b *testing.B) {
+ benchmarkSize(b, 8192, false)
+}
+
+func BenchmarkHash8BytesUnaligned(b *testing.B) {
+ benchmarkSize(b, 8, true)
+}
+
+func BenchmarkHash1KUnaligned(b *testing.B) {
+ benchmarkSize(b, 1024, true)
+}
+
+func BenchmarkHash8KUnaligned(b *testing.B) {
+ benchmarkSize(b, 8192, true)
+}
diff --git a/src/pkg/crypto/md5/md5block.go b/src/pkg/crypto/md5/md5block.go
index a887e2e05..0ca421774 100644
--- a/src/pkg/crypto/md5/md5block.go
+++ b/src/pkg/crypto/md5/md5block.go
@@ -1,172 +1,258 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
+package md5
-// MD5 block step.
-// In its own file so that a faster assembly or C version
-// can be substituted easily.
+import (
+ "runtime"
+ "unsafe"
+)
-package md5
+const x86 = runtime.GOARCH == "amd64" || runtime.GOARCH == "386"
-// table[i] = int((1<<32) * abs(sin(i+1 radians))).
-var table = []uint32{
- // round 1
- 0xd76aa478,
- 0xe8c7b756,
- 0x242070db,
- 0xc1bdceee,
- 0xf57c0faf,
- 0x4787c62a,
- 0xa8304613,
- 0xfd469501,
- 0x698098d8,
- 0x8b44f7af,
- 0xffff5bb1,
- 0x895cd7be,
- 0x6b901122,
- 0xfd987193,
- 0xa679438e,
- 0x49b40821,
-
- // round 2
- 0xf61e2562,
- 0xc040b340,
- 0x265e5a51,
- 0xe9b6c7aa,
- 0xd62f105d,
- 0x2441453,
- 0xd8a1e681,
- 0xe7d3fbc8,
- 0x21e1cde6,
- 0xc33707d6,
- 0xf4d50d87,
- 0x455a14ed,
- 0xa9e3e905,
- 0xfcefa3f8,
- 0x676f02d9,
- 0x8d2a4c8a,
-
- // round3
- 0xfffa3942,
- 0x8771f681,
- 0x6d9d6122,
- 0xfde5380c,
- 0xa4beea44,
- 0x4bdecfa9,
- 0xf6bb4b60,
- 0xbebfbc70,
- 0x289b7ec6,
- 0xeaa127fa,
- 0xd4ef3085,
- 0x4881d05,
- 0xd9d4d039,
- 0xe6db99e5,
- 0x1fa27cf8,
- 0xc4ac5665,
-
- // round 4
- 0xf4292244,
- 0x432aff97,
- 0xab9423a7,
- 0xfc93a039,
- 0x655b59c3,
- 0x8f0ccc92,
- 0xffeff47d,
- 0x85845dd1,
- 0x6fa87e4f,
- 0xfe2ce6e0,
- 0xa3014314,
- 0x4e0811a1,
- 0xf7537e82,
- 0xbd3af235,
- 0x2ad7d2bb,
- 0xeb86d391,
-}
+var littleEndian bool
-var shift1 = []uint{7, 12, 17, 22}
-var shift2 = []uint{5, 9, 14, 20}
-var shift3 = []uint{4, 11, 16, 23}
-var shift4 = []uint{6, 10, 15, 21}
+func init() {
+ x := uint32(0x04030201)
+ y := [4]byte{0x1, 0x2, 0x3, 0x4}
+ littleEndian = *(*[4]byte)(unsafe.Pointer(&x)) == y
+}
-func _Block(dig *digest, p []byte) int {
+func block(dig *digest, p []byte) {
a := dig.s[0]
b := dig.s[1]
c := dig.s[2]
d := dig.s[3]
- n := 0
- var X [16]uint32
- for len(p) >= _Chunk {
+ var X *[16]uint32
+ var xbuf [16]uint32
+ for len(p) >= chunk {
aa, bb, cc, dd := a, b, c, d
- j := 0
- for i := 0; i < 16; i++ {
- X[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24
- j += 4
+ // This is a constant condition - it is not evaluated on each iteration.
+ if x86 {
+ // MD5 was designed so that x86 processors can just iterate
+ // over the block data directly as uint32s, and we generate
+ // less code and run 1.3x faster if we take advantage of that.
+ // My apologies.
+ X = (*[16]uint32)(unsafe.Pointer(&p[0]))
+ } else if littleEndian && uintptr(unsafe.Pointer(&p[0]))&(unsafe.Alignof(uint32(0))-1) == 0 {
+ X = (*[16]uint32)(unsafe.Pointer(&p[0]))
+ } else {
+ X = &xbuf
+ j := 0
+ for i := 0; i < 16; i++ {
+ X[i&15] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24
+ j += 4
+ }
}
- // If this needs to be made faster in the future,
- // the usual trick is to unroll each of these
- // loops by a factor of 4; that lets you replace
- // the shift[] lookups with constants and,
- // with suitable variable renaming in each
- // unrolled body, delete the a, b, c, d = d, a, b, c
- // (or you can let the optimizer do the renaming).
- //
- // The index variables are uint so that % by a power
- // of two can be optimized easily by a compiler.
-
// Round 1.
- for i := uint(0); i < 16; i++ {
- x := i
- s := shift1[i%4]
- f := ((c ^ d) & b) ^ d
- a += f + X[x] + table[i]
- a = a<<s | a>>(32-s) + b
- a, b, c, d = d, a, b, c
- }
+
+ a += (((c ^ d) & b) ^ d) + X[0] + 3614090360
+ a = a<<7 | a>>(32-7) + b
+
+ d += (((b ^ c) & a) ^ c) + X[1] + 3905402710
+ d = d<<12 | d>>(32-12) + a
+
+ c += (((a ^ b) & d) ^ b) + X[2] + 606105819
+ c = c<<17 | c>>(32-17) + d
+
+ b += (((d ^ a) & c) ^ a) + X[3] + 3250441966
+ b = b<<22 | b>>(32-22) + c
+
+ a += (((c ^ d) & b) ^ d) + X[4] + 4118548399
+ a = a<<7 | a>>(32-7) + b
+
+ d += (((b ^ c) & a) ^ c) + X[5] + 1200080426
+ d = d<<12 | d>>(32-12) + a
+
+ c += (((a ^ b) & d) ^ b) + X[6] + 2821735955
+ c = c<<17 | c>>(32-17) + d
+
+ b += (((d ^ a) & c) ^ a) + X[7] + 4249261313
+ b = b<<22 | b>>(32-22) + c
+
+ a += (((c ^ d) & b) ^ d) + X[8] + 1770035416
+ a = a<<7 | a>>(32-7) + b
+
+ d += (((b ^ c) & a) ^ c) + X[9] + 2336552879
+ d = d<<12 | d>>(32-12) + a
+
+ c += (((a ^ b) & d) ^ b) + X[10] + 4294925233
+ c = c<<17 | c>>(32-17) + d
+
+ b += (((d ^ a) & c) ^ a) + X[11] + 2304563134
+ b = b<<22 | b>>(32-22) + c
+
+ a += (((c ^ d) & b) ^ d) + X[12] + 1804603682
+ a = a<<7 | a>>(32-7) + b
+
+ d += (((b ^ c) & a) ^ c) + X[13] + 4254626195
+ d = d<<12 | d>>(32-12) + a
+
+ c += (((a ^ b) & d) ^ b) + X[14] + 2792965006
+ c = c<<17 | c>>(32-17) + d
+
+ b += (((d ^ a) & c) ^ a) + X[15] + 1236535329
+ b = b<<22 | b>>(32-22) + c
// Round 2.
- for i := uint(0); i < 16; i++ {
- x := (1 + 5*i) % 16
- s := shift2[i%4]
- g := ((b ^ c) & d) ^ c
- a += g + X[x] + table[i+16]
- a = a<<s | a>>(32-s) + b
- a, b, c, d = d, a, b, c
- }
+
+ a += (((b ^ c) & d) ^ c) + X[(1+5*0)&15] + 4129170786
+ a = a<<5 | a>>(32-5) + b
+
+ d += (((a ^ b) & c) ^ b) + X[(1+5*1)&15] + 3225465664
+ d = d<<9 | d>>(32-9) + a
+
+ c += (((d ^ a) & b) ^ a) + X[(1+5*2)&15] + 643717713
+ c = c<<14 | c>>(32-14) + d
+
+ b += (((c ^ d) & a) ^ d) + X[(1+5*3)&15] + 3921069994
+ b = b<<20 | b>>(32-20) + c
+
+ a += (((b ^ c) & d) ^ c) + X[(1+5*4)&15] + 3593408605
+ a = a<<5 | a>>(32-5) + b
+
+ d += (((a ^ b) & c) ^ b) + X[(1+5*5)&15] + 38016083
+ d = d<<9 | d>>(32-9) + a
+
+ c += (((d ^ a) & b) ^ a) + X[(1+5*6)&15] + 3634488961
+ c = c<<14 | c>>(32-14) + d
+
+ b += (((c ^ d) & a) ^ d) + X[(1+5*7)&15] + 3889429448
+ b = b<<20 | b>>(32-20) + c
+
+ a += (((b ^ c) & d) ^ c) + X[(1+5*8)&15] + 568446438
+ a = a<<5 | a>>(32-5) + b
+
+ d += (((a ^ b) & c) ^ b) + X[(1+5*9)&15] + 3275163606
+ d = d<<9 | d>>(32-9) + a
+
+ c += (((d ^ a) & b) ^ a) + X[(1+5*10)&15] + 4107603335
+ c = c<<14 | c>>(32-14) + d
+
+ b += (((c ^ d) & a) ^ d) + X[(1+5*11)&15] + 1163531501
+ b = b<<20 | b>>(32-20) + c
+
+ a += (((b ^ c) & d) ^ c) + X[(1+5*12)&15] + 2850285829
+ a = a<<5 | a>>(32-5) + b
+
+ d += (((a ^ b) & c) ^ b) + X[(1+5*13)&15] + 4243563512
+ d = d<<9 | d>>(32-9) + a
+
+ c += (((d ^ a) & b) ^ a) + X[(1+5*14)&15] + 1735328473
+ c = c<<14 | c>>(32-14) + d
+
+ b += (((c ^ d) & a) ^ d) + X[(1+5*15)&15] + 2368359562
+ b = b<<20 | b>>(32-20) + c
// Round 3.
- for i := uint(0); i < 16; i++ {
- x := (5 + 3*i) % 16
- s := shift3[i%4]
- h := b ^ c ^ d
- a += h + X[x] + table[i+32]
- a = a<<s | a>>(32-s) + b
- a, b, c, d = d, a, b, c
- }
+
+ a += (b ^ c ^ d) + X[(5+3*0)&15] + 4294588738
+ a = a<<4 | a>>(32-4) + b
+
+ d += (a ^ b ^ c) + X[(5+3*1)&15] + 2272392833
+ d = d<<11 | d>>(32-11) + a
+
+ c += (d ^ a ^ b) + X[(5+3*2)&15] + 1839030562
+ c = c<<16 | c>>(32-16) + d
+
+ b += (c ^ d ^ a) + X[(5+3*3)&15] + 4259657740
+ b = b<<23 | b>>(32-23) + c
+
+ a += (b ^ c ^ d) + X[(5+3*4)&15] + 2763975236
+ a = a<<4 | a>>(32-4) + b
+
+ d += (a ^ b ^ c) + X[(5+3*5)&15] + 1272893353
+ d = d<<11 | d>>(32-11) + a
+
+ c += (d ^ a ^ b) + X[(5+3*6)&15] + 4139469664
+ c = c<<16 | c>>(32-16) + d
+
+ b += (c ^ d ^ a) + X[(5+3*7)&15] + 3200236656
+ b = b<<23 | b>>(32-23) + c
+
+ a += (b ^ c ^ d) + X[(5+3*8)&15] + 681279174
+ a = a<<4 | a>>(32-4) + b
+
+ d += (a ^ b ^ c) + X[(5+3*9)&15] + 3936430074
+ d = d<<11 | d>>(32-11) + a
+
+ c += (d ^ a ^ b) + X[(5+3*10)&15] + 3572445317
+ c = c<<16 | c>>(32-16) + d
+
+ b += (c ^ d ^ a) + X[(5+3*11)&15] + 76029189
+ b = b<<23 | b>>(32-23) + c
+
+ a += (b ^ c ^ d) + X[(5+3*12)&15] + 3654602809
+ a = a<<4 | a>>(32-4) + b
+
+ d += (a ^ b ^ c) + X[(5+3*13)&15] + 3873151461
+ d = d<<11 | d>>(32-11) + a
+
+ c += (d ^ a ^ b) + X[(5+3*14)&15] + 530742520
+ c = c<<16 | c>>(32-16) + d
+
+ b += (c ^ d ^ a) + X[(5+3*15)&15] + 3299628645
+ b = b<<23 | b>>(32-23) + c
// Round 4.
- for i := uint(0); i < 16; i++ {
- x := (7 * i) % 16
- s := shift4[i%4]
- j := c ^ (b | ^d)
- a += j + X[x] + table[i+48]
- a = a<<s | a>>(32-s) + b
- a, b, c, d = d, a, b, c
- }
+
+ a += (c ^ (b | ^d)) + X[(7*0)&15] + 4096336452
+ a = a<<6 | a>>(32-6) + b
+
+ d += (b ^ (a | ^c)) + X[(7*1)&15] + 1126891415
+ d = d<<10 | d>>(32-10) + a
+
+ c += (a ^ (d | ^b)) + X[(7*2)&15] + 2878612391
+ c = c<<15 | c>>(32-15) + d
+
+ b += (d ^ (c | ^a)) + X[(7*3)&15] + 4237533241
+ b = b<<21 | b>>(32-21) + c
+
+ a += (c ^ (b | ^d)) + X[(7*4)&15] + 1700485571
+ a = a<<6 | a>>(32-6) + b
+
+ d += (b ^ (a | ^c)) + X[(7*5)&15] + 2399980690
+ d = d<<10 | d>>(32-10) + a
+
+ c += (a ^ (d | ^b)) + X[(7*6)&15] + 4293915773
+ c = c<<15 | c>>(32-15) + d
+
+ b += (d ^ (c | ^a)) + X[(7*7)&15] + 2240044497
+ b = b<<21 | b>>(32-21) + c
+
+ a += (c ^ (b | ^d)) + X[(7*8)&15] + 1873313359
+ a = a<<6 | a>>(32-6) + b
+
+ d += (b ^ (a | ^c)) + X[(7*9)&15] + 4264355552
+ d = d<<10 | d>>(32-10) + a
+
+ c += (a ^ (d | ^b)) + X[(7*10)&15] + 2734768916
+ c = c<<15 | c>>(32-15) + d
+
+ b += (d ^ (c | ^a)) + X[(7*11)&15] + 1309151649
+ b = b<<21 | b>>(32-21) + c
+
+ a += (c ^ (b | ^d)) + X[(7*12)&15] + 4149444226
+ a = a<<6 | a>>(32-6) + b
+
+ d += (b ^ (a | ^c)) + X[(7*13)&15] + 3174756917
+ d = d<<10 | d>>(32-10) + a
+
+ c += (a ^ (d | ^b)) + X[(7*14)&15] + 718787259
+ c = c<<15 | c>>(32-15) + d
+
+ b += (d ^ (c | ^a)) + X[(7*15)&15] + 3951481745
+ b = b<<21 | b>>(32-21) + c
a += aa
b += bb
c += cc
d += dd
- p = p[_Chunk:]
- n += _Chunk
+ p = p[chunk:]
}
dig.s[0] = a
dig.s[1] = b
dig.s[2] = c
dig.s[3] = d
- return n
}
diff --git a/src/pkg/crypto/rand/example_test.go b/src/pkg/crypto/rand/example_test.go
new file mode 100644
index 000000000..5af8e46f5
--- /dev/null
+++ b/src/pkg/crypto/rand/example_test.go
@@ -0,0 +1,29 @@
+// 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.
+
+package rand_test
+
+import (
+ "bytes"
+ "crypto/rand"
+ "fmt"
+ "io"
+)
+
+// This example reads 10 cryptographically secure pseudorandom numbers from
+// rand.Reader and writes them to a byte slice.
+func ExampleRead() {
+ c := 10
+ b := make([]byte, c)
+ n, err := io.ReadFull(rand.Reader, b)
+ if n != len(b) || err != nil {
+ fmt.Println("error:", err)
+ return
+ }
+ // The slice should now contain random bytes instead of only zeroes.
+ fmt.Println(bytes.Equal(b, make([]byte, c)))
+
+ // Output:
+ // false
+}
diff --git a/src/pkg/crypto/rand/rand_test.go b/src/pkg/crypto/rand/rand_test.go
index be3a5a221..e46e61d37 100644
--- a/src/pkg/crypto/rand/rand_test.go
+++ b/src/pkg/crypto/rand/rand_test.go
@@ -7,6 +7,7 @@ package rand
import (
"bytes"
"compress/flate"
+ "io"
"testing"
)
@@ -16,9 +17,9 @@ func TestRead(t *testing.T) {
n = 1e5
}
b := make([]byte, n)
- n, err := Read(b)
+ n, err := io.ReadFull(Reader, b)
if n != len(b) || err != nil {
- t.Fatalf("Read(buf) = %d, %s", n, err)
+ t.Fatalf("ReadFull(buf) = %d, %s", n, err)
}
var z bytes.Buffer
@@ -29,3 +30,14 @@ func TestRead(t *testing.T) {
t.Fatalf("Compressed %d -> %d", len(b), z.Len())
}
}
+
+func TestReadEmpty(t *testing.T) {
+ n, err := Reader.Read(make([]byte, 0))
+ if n != 0 || err != nil {
+ t.Fatalf("Read(make([]byte, 0)) = %d, %v", n, err)
+ }
+ n, err = Reader.Read(nil)
+ if n != 0 || err != nil {
+ t.Fatalf("Read(nil) = %d, %v", n, err)
+ }
+}
diff --git a/src/pkg/crypto/rand/rand_unix.go b/src/pkg/crypto/rand/rand_unix.go
index 5eb4cda2b..18f482472 100644
--- a/src/pkg/crypto/rand/rand_unix.go
+++ b/src/pkg/crypto/rand/rand_unix.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 darwin freebsd linux netbsd openbsd
+// +build darwin freebsd linux netbsd openbsd plan9
// Unix cryptographically secure pseudorandom number
// generator.
@@ -15,6 +15,7 @@ import (
"crypto/cipher"
"io"
"os"
+ "runtime"
"sync"
"time"
)
@@ -22,7 +23,13 @@ import (
// Easy implementation: read from /dev/urandom.
// This is sufficient on Linux, OS X, and FreeBSD.
-func init() { Reader = &devReader{name: "/dev/urandom"} }
+func init() {
+ if runtime.GOOS == "plan9" {
+ Reader = newReader(nil)
+ } else {
+ Reader = &devReader{name: "/dev/urandom"}
+ }
+}
// A devReader satisfies reads by reading the file named name.
type devReader struct {
@@ -39,14 +46,17 @@ func (r *devReader) Read(b []byte) (n int, err error) {
if f == nil {
return 0, err
}
- r.f = bufio.NewReader(f)
+ if runtime.GOOS == "plan9" {
+ r.f = f
+ } else {
+ r.f = bufio.NewReader(f)
+ }
}
return r.f.Read(b)
}
// Alternate pseudo-random implementation for use on
-// systems without a reliable /dev/urandom. So far we
-// haven't needed it.
+// systems without a reliable /dev/urandom.
// newReader returns a new pseudorandom generator that
// seeds itself by reading from entropy. If entropy == nil,
diff --git a/src/pkg/crypto/rand/rand_windows.go b/src/pkg/crypto/rand/rand_windows.go
index 2b2bd4bba..82b39b64a 100644
--- a/src/pkg/crypto/rand/rand_windows.go
+++ b/src/pkg/crypto/rand/rand_windows.go
@@ -35,6 +35,10 @@ func (r *rngReader) Read(b []byte) (n int, err error) {
}
}
r.mu.Unlock()
+
+ if len(b) == 0 {
+ return 0, nil
+ }
err = syscall.CryptGenRandom(r.prov, uint32(len(b)), &b[0])
if err != nil {
return 0, os.NewSyscallError("CryptGenRandom", err)
diff --git a/src/pkg/crypto/rand/util.go b/src/pkg/crypto/rand/util.go
index 5391c1829..50e5b162b 100644
--- a/src/pkg/crypto/rand/util.go
+++ b/src/pkg/crypto/rand/util.go
@@ -10,6 +10,21 @@ import (
"math/big"
)
+// smallPrimes is a list of small, prime numbers that allows us to rapidly
+// exclude some fraction of composite candidates when searching for a random
+// prime. This list is truncated at the point where smallPrimesProduct exceeds
+// a uint64. It does not include two because we ensure that the candidates are
+// odd by construction.
+var smallPrimes = []uint8{
+ 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53,
+}
+
+// smallPrimesProduct is the product of the values in smallPrimes and allows us
+// to reduce a candidate prime by this number and then determine whether it's
+// coprime to all the elements of smallPrimes without further big.Int
+// operations.
+var smallPrimesProduct = new(big.Int).SetUint64(16294579238595022365)
+
// Prime returns a number, p, of the given size, such that p is prime
// with high probability.
func Prime(rand io.Reader, bits int) (p *big.Int, err error) {
@@ -25,6 +40,8 @@ func Prime(rand io.Reader, bits int) (p *big.Int, err error) {
bytes := make([]byte, (bits+7)/8)
p = new(big.Int)
+ bigMod := new(big.Int)
+
for {
_, err = io.ReadFull(rand, bytes)
if err != nil {
@@ -33,13 +50,51 @@ func Prime(rand io.Reader, bits int) (p *big.Int, err error) {
// Clear bits in the first byte to make sure the candidate has a size <= bits.
bytes[0] &= uint8(int(1<<b) - 1)
- // Don't let the value be too small, i.e, set the most significant bit.
- bytes[0] |= 1 << (b - 1)
+ // Don't let the value be too small, i.e, set the most significant two bits.
+ // Setting the top two bits, rather than just the top bit,
+ // means that when two of these values are multiplied together,
+ // the result isn't ever one bit short.
+ if b >= 2 {
+ bytes[0] |= 3 << (b - 2)
+ } else {
+ // Here b==1, because b cannot be zero.
+ bytes[0] |= 1
+ if len(bytes) > 1 {
+ bytes[1] |= 0x80
+ }
+ }
// Make the value odd since an even number this large certainly isn't prime.
bytes[len(bytes)-1] |= 1
p.SetBytes(bytes)
- if p.ProbablyPrime(20) {
+
+ // 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.
+ bigMod.Mod(p, smallPrimesProduct)
+ mod := bigMod.Uint64()
+
+ NextDelta:
+ for delta := uint64(0); delta < 1<<20; delta += 2 {
+ m := mod + delta
+ for _, prime := range smallPrimes {
+ if m%uint64(prime) == 0 {
+ continue NextDelta
+ }
+ }
+
+ if delta > 0 {
+ bigMod.SetUint64(delta)
+ p.Add(p, bigMod)
+ }
+ break
+ }
+
+ // There is a tiny possibility that, by adding delta, we caused
+ // the number to be one bit too long. Thus we check BitLen
+ // here.
+ if p.ProbablyPrime(20) && p.BitLen() == bits {
return
}
}
diff --git a/src/pkg/crypto/rc4/rc4.go b/src/pkg/crypto/rc4/rc4.go
index 1bb278f74..e0c33fa4b 100644
--- a/src/pkg/crypto/rc4/rc4.go
+++ b/src/pkg/crypto/rc4/rc4.go
@@ -42,17 +42,6 @@ func NewCipher(key []byte) (*Cipher, error) {
return &c, nil
}
-// XORKeyStream sets dst to the result of XORing src with the key stream.
-// Dst and src may be the same slice but otherwise should not overlap.
-func (c *Cipher) XORKeyStream(dst, src []byte) {
- for i := range src {
- c.i += 1
- c.j += c.s[c.i]
- c.s[c.i], c.s[c.j] = c.s[c.j], c.s[c.i]
- dst[i] = src[i] ^ c.s[c.s[c.i]+c.s[c.j]]
- }
-}
-
// Reset zeros the key data so that it will no longer appear in the
// process's memory.
func (c *Cipher) Reset() {
diff --git a/src/pkg/crypto/rc4/rc4_amd64.s b/src/pkg/crypto/rc4/rc4_amd64.s
new file mode 100644
index 000000000..ffe9ada85
--- /dev/null
+++ b/src/pkg/crypto/rc4/rc4_amd64.s
@@ -0,0 +1,53 @@
+// 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.
+
+// func xorKeyStream(dst, src *byte, n int, state *[256]byte, i, j *uint8)
+TEXT ·xorKeyStream(SB),7,$0
+ MOVQ dst+0(FP), DI
+ MOVQ src+8(FP), SI
+ MOVQ n+16(FP), CX
+ MOVQ state+24(FP), R8
+
+ MOVQ xPtr+32(FP), AX
+ MOVBQZX (AX), AX
+ MOVQ yPtr+40(FP), BX
+ MOVBQZX (BX), BX
+
+loop:
+ CMPQ CX, $0
+ JE done
+
+ // c.i += 1
+ INCB AX
+
+ // c.j += c.s[c.i]
+ MOVB (R8)(AX*1), R9
+ ADDB R9, BX
+
+ MOVBQZX (R8)(BX*1), R10
+
+ MOVB R10, (R8)(AX*1)
+ MOVB R9, (R8)(BX*1)
+
+ // R11 = c.s[c.i]+c.s[c.j]
+ MOVQ R10, R11
+ ADDB R9, R11
+
+ MOVB (R8)(R11*1), R11
+ MOVB (SI), R12
+ XORB R11, R12
+ MOVB R12, (DI)
+
+ INCQ SI
+ INCQ DI
+ DECQ CX
+
+ JMP loop
+done:
+ MOVQ xPtr+32(FP), R8
+ MOVB AX, (R8)
+ MOVQ yPtr+40(FP), R8
+ MOVB BX, (R8)
+
+ RET
diff --git a/src/pkg/crypto/rc4/rc4_arm.s b/src/pkg/crypto/rc4/rc4_arm.s
new file mode 100644
index 000000000..51a332f62
--- /dev/null
+++ b/src/pkg/crypto/rc4/rc4_arm.s
@@ -0,0 +1,58 @@
+// 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.
+
+// Registers
+dst = 0
+src = 1
+n = 2
+state = 3
+pi = 4
+pj = 5
+i = 6
+j = 7
+k = 8
+t = 11
+t2 = 12
+
+// func xorKeyStream(dst, src *byte, n int, state *[256]byte, i, j *uint8)
+TEXT ·xorKeyStream(SB),7,$0
+ MOVW 0(FP), R(dst)
+ MOVW 4(FP), R(src)
+ MOVW 8(FP), R(n)
+ MOVW 12(FP), R(state)
+ MOVW 16(FP), R(pi)
+ MOVW 20(FP), R(pj)
+ MOVBU (R(pi)), R(i)
+ MOVBU (R(pj)), R(j)
+ MOVW $0, R(k)
+
+loop:
+ // i += 1; j += state[i]
+ ADD $1, R(i)
+ AND $0xff, R(i)
+ MOVBU R(i)<<0(R(state)), R(t)
+ ADD R(t), R(j)
+ AND $0xff, R(j)
+
+ // swap state[i] <-> state[j]
+ MOVBU R(j)<<0(R(state)), R(t2)
+ MOVB R(t2), R(i)<<0(R(state))
+ MOVB R(t), R(j)<<0(R(state))
+
+ // dst[k] = src[k] ^ state[state[i] + state[j]]
+ ADD R(t2), R(t)
+ AND $0xff, R(t)
+ MOVBU R(t)<<0(R(state)), R(t)
+ MOVBU R(k)<<0(R(src)), R(t2)
+ EOR R(t), R(t2)
+ MOVB R(t2), R(k)<<0(R(dst))
+
+ ADD $1, R(k)
+ CMP R(k), R(n)
+ BNE loop
+
+done:
+ MOVB R(i), (R(pi))
+ MOVB R(j), (R(pj))
+ RET
diff --git a/src/pkg/crypto/rc4/rc4_asm.go b/src/pkg/crypto/rc4/rc4_asm.go
new file mode 100644
index 000000000..0b66e4a9e
--- /dev/null
+++ b/src/pkg/crypto/rc4/rc4_asm.go
@@ -0,0 +1,18 @@
+// 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 arm
+
+package rc4
+
+func xorKeyStream(dst, src *byte, n int, state *[256]byte, i, j *uint8)
+
+// XORKeyStream sets dst to the result of XORing src with the key stream.
+// Dst and src may be the same slice but otherwise should not overlap.
+func (c *Cipher) XORKeyStream(dst, src []byte) {
+ if len(src) == 0 {
+ return
+ }
+ xorKeyStream(&dst[0], &src[0], len(src), &c.s, &c.i, &c.j)
+}
diff --git a/src/pkg/crypto/rc4/rc4_ref.go b/src/pkg/crypto/rc4/rc4_ref.go
new file mode 100644
index 000000000..1018548c2
--- /dev/null
+++ b/src/pkg/crypto/rc4/rc4_ref.go
@@ -0,0 +1,20 @@
+// 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,!arm
+
+package rc4
+
+// XORKeyStream sets dst to the result of XORing src with the key stream.
+// Dst and src may be the same slice but otherwise should not overlap.
+func (c *Cipher) XORKeyStream(dst, src []byte) {
+ i, j := c.i, c.j
+ for k, v := range src {
+ i += 1
+ j += c.s[i]
+ c.s[i], c.s[j] = c.s[j], c.s[i]
+ dst[k] = v ^ c.s[c.s[i]+c.s[j]]
+ }
+ c.i, c.j = i, j
+}
diff --git a/src/pkg/crypto/rc4/rc4_test.go b/src/pkg/crypto/rc4/rc4_test.go
index 6265d9408..9e12789f7 100644
--- a/src/pkg/crypto/rc4/rc4_test.go
+++ b/src/pkg/crypto/rc4/rc4_test.go
@@ -37,6 +37,39 @@ var golden = []rc4Test{
[]byte{0x57, 0x69, 0x6b, 0x69},
[]byte{0x60, 0x44, 0xdb, 0x6d, 0x41, 0xb7},
},
+ {
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{
+ 0xde, 0x18, 0x89, 0x41, 0xa3, 0x37, 0x5d, 0x3a,
+ 0x8a, 0x06, 0x1e, 0x67, 0x57, 0x6e, 0x92, 0x6d,
+ 0xc7, 0x1a, 0x7f, 0xa3, 0xf0, 0xcc, 0xeb, 0x97,
+ 0x45, 0x2b, 0x4d, 0x32, 0x27, 0x96, 0x5f, 0x9e,
+ 0xa8, 0xcc, 0x75, 0x07, 0x6d, 0x9f, 0xb9, 0xc5,
+ 0x41, 0x7a, 0xa5, 0xcb, 0x30, 0xfc, 0x22, 0x19,
+ 0x8b, 0x34, 0x98, 0x2d, 0xbb, 0x62, 0x9e, 0xc0,
+ 0x4b, 0x4f, 0x8b, 0x05, 0xa0, 0x71, 0x08, 0x50,
+ 0x92, 0xa0, 0xc3, 0x58, 0x4a, 0x48, 0xe4, 0xa3,
+ 0x0a, 0x39, 0x7b, 0x8a, 0xcd, 0x1d, 0x00, 0x9e,
+ 0xc8, 0x7d, 0x68, 0x11, 0xf2, 0x2c, 0xf4, 0x9c,
+ 0xa3, 0xe5, 0x93, 0x54, 0xb9, 0x45, 0x15, 0x35,
+ 0xa2, 0x18, 0x7a, 0x86, 0x42, 0x6c, 0xca, 0x7d,
+ 0x5e, 0x82, 0x3e, 0xba, 0x00, 0x44, 0x12, 0x67,
+ 0x12, 0x57, 0xb8, 0xd8, 0x60, 0xae, 0x4c, 0xbd,
+ 0x4c, 0x49, 0x06, 0xbb, 0xc5, 0x35, 0xef, 0xe1,
+ 0x58, 0x7f, 0x08, 0xdb, 0x33, 0x95, 0x5c, 0xdb,
+ 0xcb, 0xad, 0x9b, 0x10, 0xf5, 0x3f, 0xc4, 0xe5,
+ 0x2c, 0x59, 0x15, 0x65, 0x51, 0x84, 0x87, 0xfe,
+ 0x08, 0x4d, 0x0e, 0x3f, 0x03, 0xde, 0xbc, 0xc9,
+ 0xda, 0x1c, 0xe9, 0x0d, 0x08, 0x5c, 0x2d, 0x8a,
+ 0x19, 0xd8, 0x37, 0x30, 0x86, 0x16, 0x36, 0x92,
+ 0x14, 0x2b, 0xd8, 0xfc, 0x5d, 0x7a, 0x73, 0x49,
+ 0x6a, 0x8e, 0x59, 0xee, 0x7e, 0xcf, 0x6b, 0x94,
+ 0x06, 0x63, 0xf4, 0xa6, 0xbe, 0xe6, 0x5b, 0xd2,
+ 0xc8, 0x5c, 0x46, 0x98, 0x6c, 0x1b, 0xef, 0x34,
+ 0x90, 0xd3, 0x7b, 0x38, 0xda, 0x85, 0xd3, 0x2e,
+ 0x97, 0x39, 0xcb, 0x23, 0x4a, 0x2b, 0xe7, 0x40,
+ },
+ },
}
func TestGolden(t *testing.T) {
@@ -51,9 +84,34 @@ func TestGolden(t *testing.T) {
c.XORKeyStream(keystream, keystream)
for j, v := range keystream {
if g.keystream[j] != v {
- t.Errorf("Failed at golden index %d", i)
+ t.Errorf("Failed at golden index %d:\n%x\nvs\n%x", i, keystream, g.keystream)
break
}
}
}
}
+
+func benchmark(b *testing.B, size int64) {
+ buf := make([]byte, size)
+ c, err := NewCipher(golden[0].key)
+ if err != nil {
+ panic(err)
+ }
+ b.SetBytes(size)
+
+ for i := 0; i < b.N; i++ {
+ c.XORKeyStream(buf, buf)
+ }
+}
+
+func BenchmarkRC4_128(b *testing.B) {
+ benchmark(b, 128)
+}
+
+func BenchmarkRC4_1K(b *testing.B) {
+ benchmark(b, 1024)
+}
+
+func BenchmarkRC4_8K(b *testing.B) {
+ benchmark(b, 8096)
+}
diff --git a/src/pkg/crypto/rsa/pkcs1v15.go b/src/pkg/crypto/rsa/pkcs1v15.go
index a32236e47..28ca5d73b 100644
--- a/src/pkg/crypto/rsa/pkcs1v15.go
+++ b/src/pkg/crypto/rsa/pkcs1v15.go
@@ -19,16 +19,19 @@ import (
// 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) {
+ if err := checkPub(pub); err != nil {
+ return nil, err
+ }
k := (pub.N.BitLen() + 7) / 8
if len(msg) > k-11 {
err = ErrMessageTooLong
return
}
- // EM = 0x02 || PS || 0x00 || M
- em := make([]byte, k-1)
- em[0] = 2
- ps, mm := em[1:len(em)-len(msg)-1], em[len(em)-len(msg):]
+ // 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)
if err != nil {
return
@@ -38,13 +41,18 @@ func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, er
m := new(big.Int).SetBytes(em)
c := encrypt(new(big.Int), pub, m)
- out = c.Bytes()
+
+ copyWithLeftPad(em, c.Bytes())
+ out = em
return
}
// DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5.
// If rand != nil, it uses RSA blinding to avoid timing side-channel attacks.
func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out []byte, err error) {
+ if err := checkPub(&priv.PublicKey); err != nil {
+ return nil, err
+ }
valid, out, err := decryptPKCS1v15(rand, priv, ciphertext)
if err == nil && valid == 0 {
err = ErrDecryption
@@ -67,6 +75,9 @@ func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out [
// Encryption Standard PKCS #1'', Daniel Bleichenbacher, Advances in Cryptology
// (Crypto '98).
func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) (err error) {
+ if err := checkPub(&priv.PublicKey); err != nil {
+ return err
+ }
k := (priv.N.BitLen() + 7) / 8
if k-(len(key)+3+8) < 0 {
err = ErrDecryption
@@ -185,9 +196,12 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []b
m := new(big.Int).SetBytes(em)
c, err := decrypt(rand, priv, m)
- if err == nil {
- s = c.Bytes()
+ if err != nil {
+ return
}
+
+ copyWithLeftPad(em, c.Bytes())
+ s = em
return
}
@@ -233,11 +247,21 @@ func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte)
func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte, err error) {
hashLen = hash.Size()
if inLen != hashLen {
- return 0, nil, errors.New("input must be hashed message")
+ return 0, nil, errors.New("crypto/rsa: input must be hashed message")
}
prefix, ok := hashPrefixes[hash]
if !ok {
- return 0, nil, errors.New("unsupported hash function")
+ return 0, nil, errors.New("crypto/rsa: unsupported hash function")
}
return
}
+
+// copyWithLeftPad copies src to the end of dest, padding with zero bytes as
+// needed.
+func copyWithLeftPad(dest, src []byte) {
+ numPaddingBytes := len(dest) - len(src)
+ for i := 0; i < numPaddingBytes; i++ {
+ dest[i] = 0
+ }
+ copy(dest[numPaddingBytes:], src)
+}
diff --git a/src/pkg/crypto/rsa/pkcs1v15_test.go b/src/pkg/crypto/rsa/pkcs1v15_test.go
index 58d5fda19..bf9219bae 100644
--- a/src/pkg/crypto/rsa/pkcs1v15_test.go
+++ b/src/pkg/crypto/rsa/pkcs1v15_test.go
@@ -57,7 +57,7 @@ func TestDecryptPKCS1v15(t *testing.T) {
t.Errorf("#%d error decrypting", i)
}
want := []byte(test.out)
- if bytes.Compare(out, want) != 0 {
+ if !bytes.Equal(out, want) {
t.Errorf("#%d got:%#v want:%#v", i, out, want)
}
}
@@ -90,7 +90,7 @@ func TestEncryptPKCS1v15(t *testing.T) {
return false
}
- if bytes.Compare(plaintext, in) != 0 {
+ if !bytes.Equal(plaintext, in) {
t.Errorf("output mismatch: %#v %#v", plaintext, in)
return false
}
@@ -132,7 +132,7 @@ func TestEncryptPKCS1v15SessionKey(t *testing.T) {
t.Errorf("#%d error decrypting", i)
}
want := []byte(test.out)
- if bytes.Compare(key, want) != 0 {
+ if !bytes.Equal(key, want) {
t.Errorf("#%d got:%#v want:%#v", i, key, want)
}
}
@@ -176,7 +176,7 @@ func TestSignPKCS1v15(t *testing.T) {
}
expected, _ := hex.DecodeString(test.out)
- if bytes.Compare(s, expected) != 0 {
+ if !bytes.Equal(s, expected) {
t.Errorf("#%d got: %x want: %x", i, s, expected)
}
}
diff --git a/src/pkg/crypto/rsa/rsa.go b/src/pkg/crypto/rsa/rsa.go
index ec77e6869..35a5f7c3c 100644
--- a/src/pkg/crypto/rsa/rsa.go
+++ b/src/pkg/crypto/rsa/rsa.go
@@ -25,6 +25,30 @@ type PublicKey struct {
E int // public exponent
}
+var (
+ errPublicModulus = errors.New("crypto/rsa: missing public modulus")
+ errPublicExponentSmall = errors.New("crypto/rsa: public exponent too small")
+ errPublicExponentLarge = errors.New("crypto/rsa: public exponent too large")
+)
+
+// checkPub sanity checks the public key before we use it.
+// We require pub.E to fit into a 32-bit integer so that we
+// do not have different behavior depending on whether
+// int is 32 or 64 bits. See also
+// http://www.imperialviolet.org/2012/03/16/rsae.html.
+func checkPub(pub *PublicKey) error {
+ if pub.N == nil {
+ return errPublicModulus
+ }
+ if pub.E < 2 {
+ return errPublicExponentSmall
+ }
+ if pub.E > 1<<31-1 {
+ return errPublicExponentLarge
+ }
+ return nil
+}
+
// A PrivateKey represents an RSA key
type PrivateKey struct {
PublicKey // public part.
@@ -37,7 +61,7 @@ type PrivateKey struct {
}
type PrecomputedValues struct {
- Dp, Dq *big.Int // D mod (P-1) (or mod Q-1)
+ Dp, Dq *big.Int // D mod (P-1) (or mod Q-1)
Qinv *big.Int // Q^-1 mod Q
// CRTValues is used for the 3rd and subsequent primes. Due to a
@@ -57,13 +81,17 @@ type CRTValue struct {
// Validate performs basic sanity checks on the key.
// It returns nil if the key is valid, or else an error describing a problem.
func (priv *PrivateKey) Validate() error {
+ if err := checkPub(&priv.PublicKey); err != nil {
+ return err
+ }
+
// Check that the prime factors are actually prime. Note that this is
// just a sanity check. Since the random witnesses chosen by
// ProbablyPrime are deterministic, given the candidate number, it's
// easy for an attack to generate composites that pass this test.
for _, prime := range priv.Primes {
if !prime.ProbablyPrime(20) {
- return errors.New("prime factor is composite")
+ return errors.New("crypto/rsa: prime factor is composite")
}
}
@@ -73,27 +101,23 @@ func (priv *PrivateKey) Validate() error {
modulus.Mul(modulus, prime)
}
if modulus.Cmp(priv.N) != 0 {
- return errors.New("invalid modulus")
+ return errors.New("crypto/rsa: invalid modulus")
}
- // Check that e and totient(Πprimes) are coprime.
- totient := new(big.Int).Set(bigOne)
+
+ // Check that de ≡ 1 mod p-1, for each prime.
+ // This implies that e is coprime to each p-1 as e has a multiplicative
+ // inverse. Therefore e is coprime to lcm(p-1,q-1,r-1,...) =
+ // exponent(ℤ/nℤ). It also implies that a^de ≡ a mod p as a^(p-1) ≡ 1
+ // mod p. Thus a^de ≡ a mod n for all a coprime to n, as required.
+ congruence := new(big.Int)
+ de := new(big.Int).SetInt64(int64(priv.E))
+ de.Mul(de, priv.D)
for _, prime := range priv.Primes {
pminus1 := new(big.Int).Sub(prime, bigOne)
- totient.Mul(totient, pminus1)
- }
- e := big.NewInt(int64(priv.E))
- gcd := new(big.Int)
- x := new(big.Int)
- y := new(big.Int)
- gcd.GCD(x, y, totient, e)
- if gcd.Cmp(bigOne) != 0 {
- return errors.New("invalid public exponent E")
- }
- // Check that de ≡ 1 (mod totient(Πprimes))
- de := new(big.Int).Mul(priv.D, e)
- de.Mod(de, totient)
- if de.Cmp(bigOne) != 0 {
- return errors.New("invalid private exponent D")
+ congruence.Mod(de, pminus1)
+ if congruence.Cmp(bigOne) != 0 {
+ return errors.New("crypto/rsa: invalid exponents")
+ }
}
return nil
}
@@ -118,7 +142,7 @@ func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (priv *Priva
priv.E = 65537
if nprimes < 2 {
- return nil, errors.New("rsa.GenerateMultiPrimeKey: nprimes must be >= 2")
+ return nil, errors.New("crypto/rsa: GenerateMultiPrimeKey: nprimes must be >= 2")
}
primes := make([]*big.Int, nprimes)
@@ -126,6 +150,20 @@ func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (priv *Priva
NextSetOfPrimes:
for {
todo := bits
+ // crypto/rand should set the top two bits in each prime.
+ // Thus each prime has the form
+ // p_i = 2^bitlen(p_i) × 0.11... (in base 2).
+ // And the product is:
+ // P = 2^todo × α
+ // where α is the product of nprimes numbers of the form 0.11...
+ //
+ // If α < 1/2 (which can happen for nprimes > 2), we need to
+ // shift todo to compensate for lost bits: the mean value of 0.11...
+ // is 7/8, so todo + shift - nprimes * log2(7/8) ~= bits - 1/2
+ // will give good results.
+ if nprimes >= 7 {
+ todo += (nprimes - 2) / 5
+ }
for i := 0; i < nprimes; i++ {
primes[i], err = rand.Prime(random, todo/(nprimes-i))
if err != nil {
@@ -151,6 +189,12 @@ NextSetOfPrimes:
pminus1.Sub(prime, bigOne)
totient.Mul(totient, pminus1)
}
+ if n.BitLen() != bits {
+ // This should never happen for nprimes == 2 because
+ // crypto/rand should set the top two bits in each prime.
+ // For nprimes > 2 we hope it does not happen often.
+ continue NextSetOfPrimes
+ }
g := new(big.Int)
priv.D = new(big.Int)
@@ -220,6 +264,9 @@ 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) {
+ 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 {
@@ -406,6 +453,9 @@ func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err er
// DecryptOAEP decrypts ciphertext using RSA-OAEP.
// If random != nil, DecryptOAEP uses RSA blinding to avoid timing side-channel attacks.
func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) (msg []byte, err 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 {
diff --git a/src/pkg/crypto/rsa/rsa_test.go b/src/pkg/crypto/rsa/rsa_test.go
index 0fb9875d0..f08cfe73c 100644
--- a/src/pkg/crypto/rsa/rsa_test.go
+++ b/src/pkg/crypto/rsa/rsa_test.go
@@ -21,15 +21,18 @@ func TestKeyGeneration(t *testing.T) {
if err != nil {
t.Errorf("failed to generate key")
}
+ if bits := priv.N.BitLen(); bits != size {
+ t.Errorf("key too short (%d vs %d)", bits, size)
+ }
testKeyBasics(t, priv)
}
func Test3PrimeKeyGeneration(t *testing.T) {
+ size := 768
if testing.Short() {
- return
+ size = 256
}
- size := 768
priv, err := GenerateMultiPrimeKey(rand.Reader, 3, size)
if err != nil {
t.Errorf("failed to generate key")
@@ -38,11 +41,11 @@ func Test3PrimeKeyGeneration(t *testing.T) {
}
func Test4PrimeKeyGeneration(t *testing.T) {
+ size := 768
if testing.Short() {
- return
+ size = 256
}
- size := 768
priv, err := GenerateMultiPrimeKey(rand.Reader, 4, size)
if err != nil {
t.Errorf("failed to generate key")
@@ -50,6 +53,42 @@ func Test4PrimeKeyGeneration(t *testing.T) {
testKeyBasics(t, priv)
}
+func TestNPrimeKeyGeneration(t *testing.T) {
+ primeSize := 64
+ maxN := 24
+ if testing.Short() {
+ primeSize = 16
+ maxN = 16
+ }
+ // Test that generation of N-prime keys works for N > 4.
+ for n := 5; n < maxN; n++ {
+ priv, err := GenerateMultiPrimeKey(rand.Reader, n, 64+n*primeSize)
+ if err == nil {
+ testKeyBasics(t, priv)
+ } else {
+ t.Errorf("failed to generate %d-prime key", n)
+ }
+ }
+}
+
+func TestGnuTLSKey(t *testing.T) {
+ // This is a key generated by `certtool --generate-privkey --bits 128`.
+ // It's such that de ≢ 1 mod φ(n), but is congruent mod the order of
+ // the group.
+ priv := &PrivateKey{
+ PublicKey: PublicKey{
+ N: fromBase10("290684273230919398108010081414538931343"),
+ E: 65537,
+ },
+ D: fromBase10("31877380284581499213530787347443987241"),
+ Primes: []*big.Int{
+ fromBase10("16775196964030542637"),
+ fromBase10("17328218193455850539"),
+ },
+ }
+ testKeyBasics(t, priv)
+}
+
func testKeyBasics(t *testing.T, priv *PrivateKey) {
if err := priv.Validate(); err != nil {
t.Errorf("Validate() failed: %s", err)
@@ -98,7 +137,7 @@ func BenchmarkRSA2048Decrypt(b *testing.B) {
}
priv.Precompute()
- c := fromBase10("1000")
+ c := fromBase10("8472002792838218989464636159316973636630013835787202418124758118372358261975764365740026024610403138425986214991379012696600761514742817632790916315594342398720903716529235119816755589383377471752116975374952783629225022962092351886861518911824745188989071172097120352727368980275252089141512321893536744324822590480751098257559766328893767334861211872318961900897793874075248286439689249972315699410830094164386544311554704755110361048571142336148077772023880664786019636334369759624917224888206329520528064315309519262325023881707530002540634660750469137117568199824615333883758410040459705787022909848740188613313")
b.StartTimer()
@@ -123,7 +162,7 @@ func Benchmark3PrimeRSA2048Decrypt(b *testing.B) {
}
priv.Precompute()
- c := fromBase10("1000")
+ c := fromBase10("8472002792838218989464636159316973636630013835787202418124758118372358261975764365740026024610403138425986214991379012696600761514742817632790916315594342398720903716529235119816755589383377471752116975374952783629225022962092351886861518911824745188989071172097120352727368980275252089141512321893536744324822590480751098257559766328893767334861211872318961900897793874075248286439689249972315699410830094164386544311554704755110361048571142336148077772023880664786019636334369759624917224888206329520528064315309519262325023881707530002540634660750469137117568199824615333883758410040459705787022909848740188613313")
b.StartTimer()
@@ -158,7 +197,7 @@ func TestEncryptOAEP(t *testing.T) {
if err != nil {
t.Errorf("#%d,%d error: %s", i, j, err)
}
- if bytes.Compare(out, message.out) != 0 {
+ if !bytes.Equal(out, message.out) {
t.Errorf("#%d,%d bad result: %x (want %x)", i, j, out, message.out)
}
}
@@ -182,7 +221,7 @@ func TestDecryptOAEP(t *testing.T) {
out, err := DecryptOAEP(sha1, nil, private, message.out, nil)
if err != nil {
t.Errorf("#%d,%d error: %s", i, j, err)
- } else if bytes.Compare(out, message.in) != 0 {
+ } else if !bytes.Equal(out, message.in) {
t.Errorf("#%d,%d bad result: %#v (want %#v)", i, j, out, message.in)
}
@@ -190,7 +229,7 @@ func TestDecryptOAEP(t *testing.T) {
out, err = DecryptOAEP(sha1, random, private, message.out, nil)
if err != nil {
t.Errorf("#%d,%d (blind) error: %s", i, j, err)
- } else if bytes.Compare(out, message.in) != 0 {
+ } else if !bytes.Equal(out, message.in) {
t.Errorf("#%d,%d (blind) bad result: %#v (want %#v)", i, j, out, message.in)
}
}
diff --git a/src/pkg/crypto/sha1/sha1.go b/src/pkg/crypto/sha1/sha1.go
index 876e7992a..7cfde47dc 100644
--- a/src/pkg/crypto/sha1/sha1.go
+++ b/src/pkg/crypto/sha1/sha1.go
@@ -21,28 +21,28 @@ const Size = 20
const BlockSize = 64
const (
- _Chunk = 64
- _Init0 = 0x67452301
- _Init1 = 0xEFCDAB89
- _Init2 = 0x98BADCFE
- _Init3 = 0x10325476
- _Init4 = 0xC3D2E1F0
+ chunk = 64
+ init0 = 0x67452301
+ init1 = 0xEFCDAB89
+ init2 = 0x98BADCFE
+ init3 = 0x10325476
+ init4 = 0xC3D2E1F0
)
// digest represents the partial evaluation of a checksum.
type digest struct {
h [5]uint32
- x [_Chunk]byte
+ x [chunk]byte
nx int
len uint64
}
func (d *digest) Reset() {
- d.h[0] = _Init0
- d.h[1] = _Init1
- d.h[2] = _Init2
- d.h[3] = _Init3
- d.h[4] = _Init4
+ d.h[0] = init0
+ d.h[1] = init1
+ d.h[2] = init2
+ d.h[3] = init3
+ d.h[4] = init4
d.nx = 0
d.len = 0
}
@@ -63,21 +63,24 @@ func (d *digest) Write(p []byte) (nn int, err error) {
d.len += uint64(nn)
if d.nx > 0 {
n := len(p)
- if n > _Chunk-d.nx {
- n = _Chunk - d.nx
+ if n > chunk-d.nx {
+ n = chunk - d.nx
}
for i := 0; i < n; i++ {
d.x[d.nx+i] = p[i]
}
d.nx += n
- if d.nx == _Chunk {
- _Block(d, d.x[0:])
+ if d.nx == chunk {
+ block(d, d.x[0:])
d.nx = 0
}
p = p[n:]
}
- n := _Block(d, p)
- p = p[n:]
+ if len(p) >= chunk {
+ n := len(p) &^ (chunk - 1)
+ block(d, p[:n])
+ p = p[n:]
+ }
if len(p) > 0 {
d.nx = copy(d.x[:], p)
}
diff --git a/src/pkg/crypto/sha1/sha1_test.go b/src/pkg/crypto/sha1/sha1_test.go
index 2dc14ac98..57cd4313e 100644
--- a/src/pkg/crypto/sha1/sha1_test.go
+++ b/src/pkg/crypto/sha1/sha1_test.go
@@ -4,10 +4,9 @@
// SHA1 hash algorithm. See RFC 3174.
-package sha1_test
+package sha1
import (
- "crypto/sha1"
"fmt"
"io"
"testing"
@@ -55,7 +54,7 @@ var golden = []sha1Test{
func TestGolden(t *testing.T) {
for i := 0; i < len(golden); i++ {
g := golden[i]
- c := sha1.New()
+ c := New()
for j := 0; j < 3; j++ {
if j < 2 {
io.WriteString(c, g.in)
@@ -74,8 +73,33 @@ func TestGolden(t *testing.T) {
}
func ExampleNew() {
- h := sha1.New()
+ h := New()
io.WriteString(h, "His money is twice tainted: 'taint yours and 'taint mine.")
fmt.Printf("% x", h.Sum(nil))
// Output: 59 7f 6a 54 00 10 f9 4c 15 d7 18 06 a9 9a 2c 87 10 e7 47 bd
}
+
+var bench = New()
+var buf = make([]byte, 8192)
+
+func benchmarkSize(b *testing.B, size int) {
+ b.SetBytes(int64(size))
+ sum := make([]byte, bench.Size())
+ for i := 0; i < b.N; i++ {
+ bench.Reset()
+ bench.Write(buf[:size])
+ bench.Sum(sum[:0])
+ }
+}
+
+func BenchmarkHash8Bytes(b *testing.B) {
+ benchmarkSize(b, 8)
+}
+
+func BenchmarkHash1K(b *testing.B) {
+ benchmarkSize(b, 1024)
+}
+
+func BenchmarkHash8K(b *testing.B) {
+ benchmarkSize(b, 8192)
+}
diff --git a/src/pkg/crypto/sha1/sha1block.go b/src/pkg/crypto/sha1/sha1block.go
index b5d32af70..1c9507c68 100644
--- a/src/pkg/crypto/sha1/sha1block.go
+++ b/src/pkg/crypto/sha1/sha1block.go
@@ -15,54 +15,67 @@ const (
_K3 = 0xCA62C1D6
)
-func _Block(dig *digest, p []byte) int {
- var w [80]uint32
+func block(dig *digest, p []byte) {
+ var w [16]uint32
- n := 0
h0, h1, h2, h3, h4 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4]
- for len(p) >= _Chunk {
+ for len(p) >= chunk {
// Can interlace the computation of w with the
// rounds below if needed for speed.
for i := 0; i < 16; i++ {
j := i * 4
w[i] = uint32(p[j])<<24 | uint32(p[j+1])<<16 | uint32(p[j+2])<<8 | uint32(p[j+3])
}
- for i := 16; i < 80; i++ {
- tmp := w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]
- w[i] = tmp<<1 | tmp>>(32-1)
- }
a, b, c, d, e := h0, h1, h2, h3, h4
// Each of the four 20-iteration rounds
// differs only in the computation of f and
// the choice of K (_K0, _K1, etc).
- for i := 0; i < 20; i++ {
+ i := 0
+ for ; i < 16; i++ {
+ f := b&c | (^b)&d
+ a5 := a<<5 | a>>(32-5)
+ b30 := b<<30 | b>>(32-30)
+ t := a5 + f + e + w[i&0xf] + _K0
+ a, b, c, d, e = t, a, b30, c, d
+ }
+ for ; i < 20; i++ {
+ tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf]
+ w[i&0xf] = tmp<<1 | tmp>>(32-1)
+
f := b&c | (^b)&d
a5 := a<<5 | a>>(32-5)
b30 := b<<30 | b>>(32-30)
- t := a5 + f + e + w[i] + _K0
+ t := a5 + f + e + w[i&0xf] + _K0
a, b, c, d, e = t, a, b30, c, d
}
- for i := 20; i < 40; i++ {
+ for ; i < 40; i++ {
+ tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf]
+ w[i&0xf] = tmp<<1 | tmp>>(32-1)
f := b ^ c ^ d
a5 := a<<5 | a>>(32-5)
b30 := b<<30 | b>>(32-30)
- t := a5 + f + e + w[i] + _K1
+ t := a5 + f + e + w[i&0xf] + _K1
a, b, c, d, e = t, a, b30, c, d
}
- for i := 40; i < 60; i++ {
- f := b&c | b&d | c&d
+ for ; i < 60; i++ {
+ tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf]
+ w[i&0xf] = tmp<<1 | tmp>>(32-1)
+ f := ((b | c) & d) | (b & c)
+
a5 := a<<5 | a>>(32-5)
b30 := b<<30 | b>>(32-30)
- t := a5 + f + e + w[i] + _K2
+ t := a5 + f + e + w[i&0xf] + _K2
a, b, c, d, e = t, a, b30, c, d
}
- for i := 60; i < 80; i++ {
+ for ; i < 80; i++ {
+ tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf]
+ w[i&0xf] = tmp<<1 | tmp>>(32-1)
f := b ^ c ^ d
a5 := a<<5 | a>>(32-5)
b30 := b<<30 | b>>(32-30)
- t := a5 + f + e + w[i] + _K3
+ t := a5 + f + e + w[i&0xf] + _K3
a, b, c, d, e = t, a, b30, c, d
}
@@ -72,10 +85,8 @@ func _Block(dig *digest, p []byte) int {
h3 += d
h4 += e
- p = p[_Chunk:]
- n += _Chunk
+ p = p[chunk:]
}
dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4] = h0, h1, h2, h3, h4
- return n
}
diff --git a/src/pkg/crypto/sha256/sha256.go b/src/pkg/crypto/sha256/sha256.go
index a61e30b42..dc0e18f50 100644
--- a/src/pkg/crypto/sha256/sha256.go
+++ b/src/pkg/crypto/sha256/sha256.go
@@ -26,29 +26,29 @@ const Size224 = 28
const BlockSize = 64
const (
- _Chunk = 64
- _Init0 = 0x6A09E667
- _Init1 = 0xBB67AE85
- _Init2 = 0x3C6EF372
- _Init3 = 0xA54FF53A
- _Init4 = 0x510E527F
- _Init5 = 0x9B05688C
- _Init6 = 0x1F83D9AB
- _Init7 = 0x5BE0CD19
- _Init0_224 = 0xC1059ED8
- _Init1_224 = 0x367CD507
- _Init2_224 = 0x3070DD17
- _Init3_224 = 0xF70E5939
- _Init4_224 = 0xFFC00B31
- _Init5_224 = 0x68581511
- _Init6_224 = 0x64F98FA7
- _Init7_224 = 0xBEFA4FA4
+ chunk = 64
+ init0 = 0x6A09E667
+ init1 = 0xBB67AE85
+ init2 = 0x3C6EF372
+ init3 = 0xA54FF53A
+ init4 = 0x510E527F
+ init5 = 0x9B05688C
+ init6 = 0x1F83D9AB
+ init7 = 0x5BE0CD19
+ init0_224 = 0xC1059ED8
+ init1_224 = 0x367CD507
+ init2_224 = 0x3070DD17
+ init3_224 = 0xF70E5939
+ init4_224 = 0xFFC00B31
+ init5_224 = 0x68581511
+ init6_224 = 0x64F98FA7
+ init7_224 = 0xBEFA4FA4
)
// digest represents the partial evaluation of a checksum.
type digest struct {
h [8]uint32
- x [_Chunk]byte
+ x [chunk]byte
nx int
len uint64
is224 bool // mark if this digest is SHA-224
@@ -56,23 +56,23 @@ type digest struct {
func (d *digest) Reset() {
if !d.is224 {
- d.h[0] = _Init0
- d.h[1] = _Init1
- d.h[2] = _Init2
- d.h[3] = _Init3
- d.h[4] = _Init4
- d.h[5] = _Init5
- d.h[6] = _Init6
- d.h[7] = _Init7
+ d.h[0] = init0
+ d.h[1] = init1
+ d.h[2] = init2
+ d.h[3] = init3
+ d.h[4] = init4
+ d.h[5] = init5
+ d.h[6] = init6
+ d.h[7] = init7
} else {
- d.h[0] = _Init0_224
- d.h[1] = _Init1_224
- d.h[2] = _Init2_224
- d.h[3] = _Init3_224
- d.h[4] = _Init4_224
- d.h[5] = _Init5_224
- d.h[6] = _Init6_224
- d.h[7] = _Init7_224
+ d.h[0] = init0_224
+ d.h[1] = init1_224
+ d.h[2] = init2_224
+ d.h[3] = init3_224
+ d.h[4] = init4_224
+ d.h[5] = init5_224
+ d.h[6] = init6_224
+ d.h[7] = init7_224
}
d.nx = 0
d.len = 0
@@ -107,21 +107,24 @@ func (d *digest) Write(p []byte) (nn int, err error) {
d.len += uint64(nn)
if d.nx > 0 {
n := len(p)
- if n > _Chunk-d.nx {
- n = _Chunk - d.nx
+ if n > chunk-d.nx {
+ n = chunk - d.nx
}
for i := 0; i < n; i++ {
d.x[d.nx+i] = p[i]
}
d.nx += n
- if d.nx == _Chunk {
- _Block(d, d.x[0:])
+ if d.nx == chunk {
+ block(d, d.x[0:])
d.nx = 0
}
p = p[n:]
}
- n := _Block(d, p)
- p = p[n:]
+ if len(p) >= chunk {
+ n := len(p) &^ (chunk - 1)
+ block(d, p[:n])
+ p = p[n:]
+ }
if len(p) > 0 {
d.nx = copy(d.x[:], p)
}
diff --git a/src/pkg/crypto/sha256/sha256_test.go b/src/pkg/crypto/sha256/sha256_test.go
index a6efb3754..29bf1619a 100644
--- a/src/pkg/crypto/sha256/sha256_test.go
+++ b/src/pkg/crypto/sha256/sha256_test.go
@@ -123,3 +123,28 @@ func TestGolden(t *testing.T) {
}
}
}
+
+var bench = New()
+var buf = make([]byte, 8192)
+
+func benchmarkSize(b *testing.B, size int) {
+ b.SetBytes(int64(size))
+ sum := make([]byte, bench.Size())
+ for i := 0; i < b.N; i++ {
+ bench.Reset()
+ bench.Write(buf[:size])
+ bench.Sum(sum[:0])
+ }
+}
+
+func BenchmarkHash8Bytes(b *testing.B) {
+ benchmarkSize(b, 8)
+}
+
+func BenchmarkHash1K(b *testing.B) {
+ benchmarkSize(b, 1024)
+}
+
+func BenchmarkHash8K(b *testing.B) {
+ benchmarkSize(b, 8192)
+}
diff --git a/src/pkg/crypto/sha256/sha256block.go b/src/pkg/crypto/sha256/sha256block.go
index 7b0f55444..2ac49100a 100644
--- a/src/pkg/crypto/sha256/sha256block.go
+++ b/src/pkg/crypto/sha256/sha256block.go
@@ -75,11 +75,10 @@ var _K = []uint32{
0xc67178f2,
}
-func _Block(dig *digest, p []byte) int {
+func block(dig *digest, p []byte) {
var w [64]uint32
- n := 0
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 {
+ for len(p) >= chunk {
// Can interlace the computation of w with the
// rounds below if needed for speed.
for i := 0; i < 16; i++ {
@@ -87,10 +86,10 @@ func _Block(dig *digest, p []byte) int {
w[i] = uint32(p[j])<<24 | uint32(p[j+1])<<16 | uint32(p[j+2])<<8 | uint32(p[j+3])
}
for i := 16; i < 64; i++ {
- t1 := (w[i-2]>>17 | w[i-2]<<(32-17)) ^ (w[i-2]>>19 | w[i-2]<<(32-19)) ^ (w[i-2] >> 10)
-
- t2 := (w[i-15]>>7 | w[i-15]<<(32-7)) ^ (w[i-15]>>18 | w[i-15]<<(32-18)) ^ (w[i-15] >> 3)
-
+ v1 := w[i-2]
+ t1 := (v1>>17 | v1<<(32-17)) ^ (v1>>19 | v1<<(32-19)) ^ (v1 >> 10)
+ v2 := w[i-15]
+ t2 := (v2>>7 | v2<<(32-7)) ^ (v2>>18 | v2<<(32-18)) ^ (v2 >> 3)
w[i] = t1 + w[i-7] + t2 + w[i-16]
}
@@ -120,10 +119,8 @@ func _Block(dig *digest, p []byte) int {
h6 += g
h7 += h
- p = p[_Chunk:]
- n += _Chunk
+ p = p[chunk:]
}
dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] = h0, h1, h2, h3, h4, h5, h6, h7
- return n
}
diff --git a/src/pkg/crypto/sha512/sha512.go b/src/pkg/crypto/sha512/sha512.go
index a245fd68e..4aec52938 100644
--- a/src/pkg/crypto/sha512/sha512.go
+++ b/src/pkg/crypto/sha512/sha512.go
@@ -26,29 +26,29 @@ const Size384 = 48
const BlockSize = 128
const (
- _Chunk = 128
- _Init0 = 0x6a09e667f3bcc908
- _Init1 = 0xbb67ae8584caa73b
- _Init2 = 0x3c6ef372fe94f82b
- _Init3 = 0xa54ff53a5f1d36f1
- _Init4 = 0x510e527fade682d1
- _Init5 = 0x9b05688c2b3e6c1f
- _Init6 = 0x1f83d9abfb41bd6b
- _Init7 = 0x5be0cd19137e2179
- _Init0_384 = 0xcbbb9d5dc1059ed8
- _Init1_384 = 0x629a292a367cd507
- _Init2_384 = 0x9159015a3070dd17
- _Init3_384 = 0x152fecd8f70e5939
- _Init4_384 = 0x67332667ffc00b31
- _Init5_384 = 0x8eb44a8768581511
- _Init6_384 = 0xdb0c2e0d64f98fa7
- _Init7_384 = 0x47b5481dbefa4fa4
+ chunk = 128
+ init0 = 0x6a09e667f3bcc908
+ init1 = 0xbb67ae8584caa73b
+ init2 = 0x3c6ef372fe94f82b
+ init3 = 0xa54ff53a5f1d36f1
+ init4 = 0x510e527fade682d1
+ init5 = 0x9b05688c2b3e6c1f
+ init6 = 0x1f83d9abfb41bd6b
+ init7 = 0x5be0cd19137e2179
+ init0_384 = 0xcbbb9d5dc1059ed8
+ init1_384 = 0x629a292a367cd507
+ init2_384 = 0x9159015a3070dd17
+ init3_384 = 0x152fecd8f70e5939
+ init4_384 = 0x67332667ffc00b31
+ init5_384 = 0x8eb44a8768581511
+ init6_384 = 0xdb0c2e0d64f98fa7
+ init7_384 = 0x47b5481dbefa4fa4
)
// digest represents the partial evaluation of a checksum.
type digest struct {
h [8]uint64
- x [_Chunk]byte
+ x [chunk]byte
nx int
len uint64
is384 bool // mark if this digest is SHA-384
@@ -56,23 +56,23 @@ type digest struct {
func (d *digest) Reset() {
if !d.is384 {
- d.h[0] = _Init0
- d.h[1] = _Init1
- d.h[2] = _Init2
- d.h[3] = _Init3
- d.h[4] = _Init4
- d.h[5] = _Init5
- d.h[6] = _Init6
- d.h[7] = _Init7
+ d.h[0] = init0
+ d.h[1] = init1
+ d.h[2] = init2
+ d.h[3] = init3
+ d.h[4] = init4
+ d.h[5] = init5
+ d.h[6] = init6
+ d.h[7] = init7
} else {
- d.h[0] = _Init0_384
- d.h[1] = _Init1_384
- d.h[2] = _Init2_384
- d.h[3] = _Init3_384
- d.h[4] = _Init4_384
- d.h[5] = _Init5_384
- d.h[6] = _Init6_384
- d.h[7] = _Init7_384
+ d.h[0] = init0_384
+ d.h[1] = init1_384
+ d.h[2] = init2_384
+ d.h[3] = init3_384
+ d.h[4] = init4_384
+ d.h[5] = init5_384
+ d.h[6] = init6_384
+ d.h[7] = init7_384
}
d.nx = 0
d.len = 0
@@ -107,21 +107,24 @@ func (d *digest) Write(p []byte) (nn int, err error) {
d.len += uint64(nn)
if d.nx > 0 {
n := len(p)
- if n > _Chunk-d.nx {
- n = _Chunk - d.nx
+ if n > chunk-d.nx {
+ n = chunk - d.nx
}
for i := 0; i < n; i++ {
d.x[d.nx+i] = p[i]
}
d.nx += n
- if d.nx == _Chunk {
- _Block(d, d.x[0:])
+ if d.nx == chunk {
+ block(d, d.x[0:])
d.nx = 0
}
p = p[n:]
}
- n := _Block(d, p)
- p = p[n:]
+ if len(p) >= chunk {
+ n := len(p) &^ (chunk - 1)
+ block(d, p[:n])
+ p = p[n:]
+ }
if len(p) > 0 {
d.nx = copy(d.x[:], p)
}
diff --git a/src/pkg/crypto/sha512/sha512_test.go b/src/pkg/crypto/sha512/sha512_test.go
index a70f7c54e..6eafb1b5f 100644
--- a/src/pkg/crypto/sha512/sha512_test.go
+++ b/src/pkg/crypto/sha512/sha512_test.go
@@ -123,3 +123,28 @@ func TestGolden(t *testing.T) {
}
}
}
+
+var bench = New()
+var buf = make([]byte, 8192)
+
+func benchmarkSize(b *testing.B, size int) {
+ b.SetBytes(int64(size))
+ sum := make([]byte, bench.Size())
+ for i := 0; i < b.N; i++ {
+ bench.Reset()
+ bench.Write(buf[:size])
+ bench.Sum(sum[:0])
+ }
+}
+
+func BenchmarkHash8Bytes(b *testing.B) {
+ benchmarkSize(b, 8)
+}
+
+func BenchmarkHash1K(b *testing.B) {
+ benchmarkSize(b, 1024)
+}
+
+func BenchmarkHash8K(b *testing.B) {
+ benchmarkSize(b, 8192)
+}
diff --git a/src/pkg/crypto/sha512/sha512block.go b/src/pkg/crypto/sha512/sha512block.go
index 6b7506287..3577b4f3d 100644
--- a/src/pkg/crypto/sha512/sha512block.go
+++ b/src/pkg/crypto/sha512/sha512block.go
@@ -91,20 +91,20 @@ var _K = []uint64{
0x6c44198c4a475817,
}
-func _Block(dig *digest, p []byte) int {
+func block(dig *digest, p []byte) {
var w [80]uint64
- n := 0
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 {
+ for len(p) >= chunk {
for i := 0; i < 16; i++ {
j := i * 8
w[i] = uint64(p[j])<<56 | uint64(p[j+1])<<48 | uint64(p[j+2])<<40 | uint64(p[j+3])<<32 |
uint64(p[j+4])<<24 | uint64(p[j+5])<<16 | uint64(p[j+6])<<8 | uint64(p[j+7])
}
for i := 16; i < 80; i++ {
- t1 := (w[i-2]>>19 | w[i-2]<<(64-19)) ^ (w[i-2]>>61 | w[i-2]<<(64-61)) ^ (w[i-2] >> 6)
-
- t2 := (w[i-15]>>1 | w[i-15]<<(64-1)) ^ (w[i-15]>>8 | w[i-15]<<(64-8)) ^ (w[i-15] >> 7)
+ v1 := w[i-2]
+ t1 := (v1>>19 | v1<<(64-19)) ^ (v1>>61 | v1<<(64-61)) ^ (v1 >> 6)
+ v2 := w[i-15]
+ t2 := (v2>>1 | v2<<(64-1)) ^ (v2>>8 | v2<<(64-8)) ^ (v2 >> 7)
w[i] = t1 + w[i-7] + t2 + w[i-16]
}
@@ -135,10 +135,8 @@ func _Block(dig *digest, p []byte) int {
h6 += g
h7 += h
- p = p[_Chunk:]
- n += _Chunk
+ p = p[chunk:]
}
dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] = h0, h1, h2, h3, h4, h5, h6, h7
- return n
}
diff --git a/src/pkg/crypto/tls/cipher_suites.go b/src/pkg/crypto/tls/cipher_suites.go
index 5039f319f..a647e19aa 100644
--- a/src/pkg/crypto/tls/cipher_suites.go
+++ b/src/pkg/crypto/tls/cipher_suites.go
@@ -55,9 +55,11 @@ var cipherSuites = []*cipherSuite{
{TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, false, cipherRC4, macSHA1},
{TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, false, cipher3DES, macSHA1},
{TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, false, cipherAES, macSHA1},
+ {TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, false, cipherAES, macSHA1},
{TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, true, cipherRC4, macSHA1},
{TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, true, cipher3DES, macSHA1},
{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, true, cipherAES, macSHA1},
+ {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, true, cipherAES, macSHA1},
}
func cipherRC4(key, iv []byte, isRead bool) interface{} {
@@ -182,7 +184,9 @@ const (
TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005
TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000a
TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f
+ TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035
TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xc011
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xc012
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013
+ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xc014
)
diff --git a/src/pkg/crypto/tls/common.go b/src/pkg/crypto/tls/common.go
index 4ba0bf874..a888df762 100644
--- a/src/pkg/crypto/tls/common.go
+++ b/src/pkg/crypto/tls/common.go
@@ -41,6 +41,7 @@ const (
const (
typeClientHello uint8 = 1
typeServerHello uint8 = 2
+ typeNewSessionTicket uint8 = 4
typeCertificate uint8 = 11
typeServerKeyExchange uint8 = 12
typeCertificateRequest uint8 = 13
@@ -63,6 +64,7 @@ var (
extensionStatusRequest uint16 = 5
extensionSupportedCurves uint16 = 10
extensionSupportedPoints uint16 = 11
+ extensionSessionTicket uint16 = 35
extensionNextProtoNeg uint16 = 13172 // not IANA assigned
)
@@ -97,6 +99,7 @@ const (
// ConnectionState records basic TLS details about the connection.
type ConnectionState struct {
HandshakeComplete bool
+ DidResume bool
CipherSuite uint16
NegotiatedProtocol string
NegotiatedProtocolIsMutual bool
@@ -180,6 +183,28 @@ type Config struct {
// CipherSuites is a list of supported cipher suites. If CipherSuites
// is nil, TLS uses a list of suites supported by the implementation.
CipherSuites []uint16
+
+ // PreferServerCipherSuites controls whether the server selects the
+ // client's most preferred ciphersuite, or the server's most preferred
+ // ciphersuite. If true then the server's preference, as expressed in
+ // the order of elements in CipherSuites, is used.
+ PreferServerCipherSuites bool
+
+ // SessionTicketsDisabled may be set to true to disable session ticket
+ // (resumption) support.
+ SessionTicketsDisabled bool
+
+ // SessionTicketKey is used by TLS servers to provide session
+ // resumption. See RFC 5077. If zero, it will be filled with
+ // random data before the first server handshake.
+ //
+ // If multiple servers are terminating connections for the same host
+ // they should all have the same SessionTicketKey. If the
+ // SessionTicketKey leaks, previously recorded and future TLS
+ // connections using that key are compromised.
+ SessionTicketKey [32]byte
+
+ serverInitOnce sync.Once
}
func (c *Config) rand() io.Reader {
diff --git a/src/pkg/crypto/tls/conn.go b/src/pkg/crypto/tls/conn.go
index 2a5115dc6..d8c2be00a 100644
--- a/src/pkg/crypto/tls/conn.go
+++ b/src/pkg/crypto/tls/conn.go
@@ -31,6 +31,7 @@ type Conn struct {
haveVers bool // version has been negotiated
config *Config // configuration passed to constructor
handshakeComplete bool
+ didResume bool // whether this connection was a session resumption
cipherSuite uint16
ocspResponse []byte // stapled OCSP response
peerCertificates []*x509.Certificate
@@ -44,8 +45,7 @@ type Conn struct {
clientProtocolFallback bool
// first permanent error
- errMutex sync.Mutex
- err error
+ connErr
// input/output
in, out halfConn // in.Mutex < out.Mutex
@@ -56,21 +56,25 @@ type Conn struct {
tmp [16]byte
}
-func (c *Conn) setError(err error) error {
- c.errMutex.Lock()
- defer c.errMutex.Unlock()
+type connErr struct {
+ mu sync.Mutex
+ value error
+}
+
+func (e *connErr) setError(err error) error {
+ e.mu.Lock()
+ defer e.mu.Unlock()
- if c.err == nil {
- c.err = err
+ if e.value == nil {
+ e.value = err
}
return err
}
-func (c *Conn) error() error {
- c.errMutex.Lock()
- defer c.errMutex.Unlock()
-
- return c.err
+func (e *connErr) error() error {
+ e.mu.Lock()
+ defer e.mu.Unlock()
+ return e.value
}
// Access to net.Conn methods.
@@ -487,6 +491,16 @@ Again:
return err
}
typ := recordType(b.data[0])
+
+ // No valid TLS record has a type of 0x80, however SSLv2 handshakes
+ // start with a uint16 length where the MSB is set and the first record
+ // is always < 256 bytes long. Therefore typ == 0x80 strongly suggests
+ // an SSLv2 client.
+ if want == recordTypeHandshake && typ == 0x80 {
+ c.sendAlert(alertProtocolVersion)
+ return errors.New("tls: unsupported SSLv2 handshake received")
+ }
+
vers := uint16(b.data[1])<<8 | uint16(b.data[2])
n := int(b.data[3])<<8 | int(b.data[4])
if c.haveVers && vers != c.vers {
@@ -499,7 +513,7 @@ Again:
// First message, be extra suspicious:
// this might not be a TLS client.
// Bail out before reading a full 'body', if possible.
- // The current max version is 3.1.
+ // The current max version is 3.1.
// If the version is >= 16.0, it's probably not real.
// Similarly, a clientHello message encodes in
// well under a kilobyte. If the length is >= 12 kB,
@@ -590,9 +604,11 @@ Again:
// sendAlert sends a TLS alert message.
// c.out.Mutex <= L.
func (c *Conn) sendAlertLocked(err alert) error {
- c.tmp[0] = alertLevelError
- if err == alertNoRenegotiation {
+ switch err {
+ case alertNoRenegotiation, alertCloseNotify:
c.tmp[0] = alertLevelWarning
+ default:
+ c.tmp[0] = alertLevelError
}
c.tmp[1] = byte(err)
c.writeRecord(recordTypeAlert, c.tmp[0:2])
@@ -650,8 +666,7 @@ func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) {
c.tmp[0] = alertLevelError
c.tmp[1] = byte(err.(alert))
c.writeRecord(recordTypeAlert, c.tmp[0:2])
- c.err = &net.OpError{Op: "local error", Err: err}
- return n, c.err
+ return n, c.setError(&net.OpError{Op: "local error", Err: err})
}
}
return
@@ -662,8 +677,8 @@ func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) {
// c.in.Mutex < L; c.out.Mutex < L.
func (c *Conn) readHandshake() (interface{}, error) {
for c.hand.Len() < 4 {
- if c.err != nil {
- return nil, c.err
+ if err := c.error(); err != nil {
+ return nil, err
}
if err := c.readRecord(recordTypeHandshake); err != nil {
return nil, err
@@ -674,11 +689,11 @@ func (c *Conn) readHandshake() (interface{}, error) {
n := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
if n > maxHandshake {
c.sendAlert(alertInternalError)
- return nil, c.err
+ return nil, c.error()
}
for c.hand.Len() < 4+n {
- if c.err != nil {
- return nil, c.err
+ if err := c.error(); err != nil {
+ return nil, err
}
if err := c.readRecord(recordTypeHandshake); err != nil {
return nil, err
@@ -728,12 +743,12 @@ func (c *Conn) readHandshake() (interface{}, error) {
// Write writes data to the connection.
func (c *Conn) Write(b []byte) (int, error) {
- if c.err != nil {
- return 0, c.err
+ if err := c.error(); err != nil {
+ return 0, err
}
- if c.err = c.Handshake(); c.err != nil {
- return 0, c.err
+ if err := c.Handshake(); err != nil {
+ return 0, c.setError(err)
}
c.out.Lock()
@@ -743,9 +758,28 @@ func (c *Conn) Write(b []byte) (int, error) {
return 0, alertInternalError
}
- var n int
- n, c.err = c.writeRecord(recordTypeApplicationData, b)
- return n, c.err
+ // SSL 3.0 and TLS 1.0 are susceptible to a chosen-plaintext
+ // attack when using block mode ciphers due to predictable IVs.
+ // This can be prevented by splitting each Application Data
+ // record into two records, effectively randomizing the IV.
+ //
+ // http://www.openssl.org/~bodo/tls-cbc.txt
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=665814
+ // http://www.imperialviolet.org/2012/01/15/beastfollowup.html
+
+ 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])
+ if err != nil {
+ return n, c.setError(err)
+ }
+ m, b = 1, b[1:]
+ }
+ }
+
+ n, err := c.writeRecord(recordTypeApplicationData, b)
+ return n + m, c.setError(err)
}
// Read can be made to time out and return a net.Error with Timeout() == true
@@ -758,14 +792,14 @@ func (c *Conn) Read(b []byte) (n int, err error) {
c.in.Lock()
defer c.in.Unlock()
- for c.input == nil && c.err == nil {
+ for c.input == nil && c.error() == nil {
if err := c.readRecord(recordTypeApplicationData); err != nil {
// Soft error, like EAGAIN
return 0, err
}
}
- if c.err != nil {
- return 0, c.err
+ if err := c.error(); err != nil {
+ return 0, err
}
n, err = c.input.Read(b)
if c.input.off >= len(c.input.data) {
@@ -819,6 +853,7 @@ func (c *Conn) ConnectionState() ConnectionState {
state.HandshakeComplete = c.handshakeComplete
if c.handshakeComplete {
state.NegotiatedProtocol = c.clientProtocol
+ state.DidResume = c.didResume
state.NegotiatedProtocolIsMutual = !c.clientProtocolFallback
state.CipherSuite = c.cipherSuite
state.PeerCertificates = c.peerCertificates
diff --git a/src/pkg/crypto/tls/generate_cert.go b/src/pkg/crypto/tls/generate_cert.go
index 84be5bfd8..215644d24 100644
--- a/src/pkg/crypto/tls/generate_cert.go
+++ b/src/pkg/crypto/tls/generate_cert.go
@@ -16,36 +16,80 @@ import (
"crypto/x509/pkix"
"encoding/pem"
"flag"
+ "fmt"
"log"
"math/big"
+ "net"
"os"
+ "strings"
"time"
)
-var hostName *string = flag.String("host", "127.0.0.1", "Hostname to generate a certificate for")
+var (
+ host = flag.String("host", "", "Comma-separated hostnames and IPs to generate a certificate for")
+ validFrom = flag.String("start-date", "", "Creation date formatted as Jan 1 15:04:05 2011")
+ validFor = flag.Duration("duration", 365*24*time.Hour, "Duration that certificate is valid for")
+ isCA = flag.Bool("ca", false, "whether this cert should be its own Certificate Authority")
+ rsaBits = flag.Int("rsa-bits", 1024, "Size of RSA key to generate")
+)
func main() {
flag.Parse()
- priv, err := rsa.GenerateKey(rand.Reader, 1024)
+ if len(*host) == 0 {
+ log.Fatalf("Missing required --host parameter")
+ }
+
+ priv, err := rsa.GenerateKey(rand.Reader, *rsaBits)
if err != nil {
log.Fatalf("failed to generate private key: %s", err)
return
}
- now := time.Now()
+ var notBefore time.Time
+ if len(*validFrom) == 0 {
+ notBefore = time.Now()
+ } else {
+ notBefore, err = time.Parse("Jan 2 15:04:05 2006", *validFrom)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Failed to parse creation date: %s\n", err)
+ os.Exit(1)
+ }
+ }
+
+ notAfter := notBefore.Add(*validFor)
+
+ // end of ASN.1 time
+ endOfTime := time.Date(2049, 12, 31, 23, 59, 59, 0, time.UTC)
+ if notAfter.After(endOfTime) {
+ notAfter = endOfTime
+ }
template := x509.Certificate{
SerialNumber: new(big.Int).SetInt64(0),
Subject: pkix.Name{
- CommonName: *hostName,
Organization: []string{"Acme Co"},
},
- NotBefore: now.Add(-5 * time.Minute).UTC(),
- NotAfter: now.AddDate(1, 0, 0).UTC(), // valid for 1 year.
+ NotBefore: notBefore,
+ NotAfter: notAfter,
+
+ KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
+ ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
+ BasicConstraintsValid: true,
+ }
+
+ hosts := strings.Split(*host, ",")
+ for _, h := range hosts {
+ if ip := net.ParseIP(h); ip != nil {
+ template.IPAddresses = append(template.IPAddresses, ip)
+ } else {
+ template.DNSNames = append(template.DNSNames, h)
+ }
+ }
- SubjectKeyId: []byte{1, 2, 3, 4},
- KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
+ if *isCA {
+ template.IsCA = true
+ template.KeyUsage |= x509.KeyUsageCertSign
}
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
diff --git a/src/pkg/crypto/tls/handshake_client.go b/src/pkg/crypto/tls/handshake_client.go
index 2877f1738..7db13bf70 100644
--- a/src/pkg/crypto/tls/handshake_client.go
+++ b/src/pkg/crypto/tls/handshake_client.go
@@ -278,8 +278,9 @@ func (c *Conn) clientHandshake() error {
c.writeRecord(recordTypeHandshake, certVerify.marshal())
}
- masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
- keysFromPreMasterSecret(c.vers, preMasterSecret, hello.random, serverHello.random, suite.macLen, suite.keyLen, suite.ivLen)
+ masterSecret := masterFromPreMasterSecret(c.vers, preMasterSecret, hello.random, serverHello.random)
+ clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
+ keysFromMasterSecret(c.vers, masterSecret, hello.random, serverHello.random, suite.macLen, suite.keyLen, suite.ivLen)
clientCipher := suite.cipher(clientKey, clientIV, false /* not for reading */)
clientHash := suite.mac(c.vers, clientMAC)
@@ -306,8 +307,8 @@ func (c *Conn) clientHandshake() error {
serverHash := suite.mac(c.vers, serverMAC)
c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
c.readRecord(recordTypeChangeCipherSpec)
- if c.err != nil {
- return c.err
+ if err := c.error(); err != nil {
+ return err
}
msg, err = c.readHandshake()
diff --git a/src/pkg/crypto/tls/handshake_client_test.go b/src/pkg/crypto/tls/handshake_client_test.go
index 8c56daaf6..9673947a4 100644
--- a/src/pkg/crypto/tls/handshake_client_test.go
+++ b/src/pkg/crypto/tls/handshake_client_test.go
@@ -9,6 +9,7 @@ import (
"flag"
"io"
"net"
+ "os"
"testing"
)
@@ -39,7 +40,15 @@ func testClientScript(t *testing.T, name string, clientScript [][]byte, config *
}
func TestHandshakeClientRC4(t *testing.T) {
- testClientScript(t, "RC4", rc4ClientScript, testConfig)
+ var config = *testConfig
+ config.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA}
+ testClientScript(t, "RC4", rc4ClientScript, &config)
+}
+
+func TestHandshakeClientECDHEAES(t *testing.T) {
+ var config = *testConfig
+ config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}
+ testClientScript(t, "ECDHE-AES", ecdheAESClientScript, &config)
}
var connect = flag.Bool("connect", false, "connect to a TLS server on :10443")
@@ -49,25 +58,33 @@ func TestRunClient(t *testing.T) {
return
}
- testConfig.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA}
-
- conn, err := Dial("tcp", "127.0.0.1:10443", testConfig)
+ tcpConn, err := net.Dial("tcp", "127.0.0.1:10443")
if err != nil {
t.Fatal(err)
}
+ record := &recordingConn{
+ Conn: tcpConn,
+ }
+
+ config := GetTestConfig()
+ conn := Client(record, config)
+ if err := conn.Handshake(); err != nil {
+ t.Fatalf("error from TLS handshake: %s", err)
+ }
+
conn.Write([]byte("hello\n"))
conn.Close()
+
+ record.WriteTo(os.Stdout)
}
// Script of interaction with gnutls implementation.
// The values for this test are obtained by building and running in client mode:
-// % go test -run "TestRunClient" -connect
-// and then:
-// % gnutls-serv -p 10443 --debug 100 --x509keyfile key.pem --x509certfile cert.pem -a > /tmp/log 2>&1
-// % python parse-gnutls-cli-debug-log.py < /tmp/log
+// % go test -test.run "TestRunClient" -connect
+// The recorded bytes are written to stdout.
//
-// Where key.pem is:
+// The server private key is:
// -----BEGIN RSA PRIVATE KEY-----
// MIIBPAIBAAJBAJ+zw4Qnlf8SMVIPFe9GEcStgOY2Ww/dgNdhjeD8ckUJNP5VZkVD
// TGiXav6ooKXfX3j/7tdkuD8Ey2//Kv7+ue0CAwEAAQJAN6W31vDEP2DjdqhzCDDu
@@ -78,17 +95,20 @@ func TestRunClient(t *testing.T) {
// vnlEGo8K85u+KwIOimM48ZG8oTk7iFdkqLJR1utT3aU=
// -----END RSA PRIVATE KEY-----
//
-// and cert.pem is:
+// and certificate is:
// -----BEGIN CERTIFICATE-----
-// MIIBoDCCAUoCAQAwDQYJKoZIhvcNAQEEBQAwYzELMAkGA1UEBhMCQVUxEzARBgNV
-// BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMSMwIQYD
-// VQQDExpTZXJ2ZXIgdGVzdCBjZXJ0ICg1MTIgYml0KTAeFw05NzA5MDkwMzQxMjZa
-// Fw05NzEwMDkwMzQxMjZaMF4xCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0
-// YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxFzAVBgNVBAMT
-// DkVyaWMgdGhlIFlvdW5nMFEwCQYFKw4DAgwFAANEAAJBALVEqPODnpI4rShlY8S7
-// tB713JNvabvn6Gned7zylwLLiXQAo/PAT6mfdWPTyCX9RlId/Aroh1ou893BA32Q
-// sggwDQYJKoZIhvcNAQEEBQADQQCU5SSgapJSdRXJoX+CpCvFy+JVh9HpSjCpSNKO
-// 19raHv98hKAUJuP9HyM+SUsffO6mAIgitUaqW8/wDMePhEC3
+// MIICKzCCAdWgAwIBAgIJALE1E2URIMWSMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
+// BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
+// aWRnaXRzIFB0eSBMdGQwHhcNMTIwNDA2MTcxMDEzWhcNMTUwNDA2MTcxMDEzWjBF
+// MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
+// ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJ+z
+// w4Qnlf8SMVIPFe9GEcStgOY2Ww/dgNdhjeD8ckUJNP5VZkVDTGiXav6ooKXfX3j/
+// 7tdkuD8Ey2//Kv7+ue0CAwEAAaOBpzCBpDAdBgNVHQ4EFgQUeKaXmmO1xaGlM7oi
+// fCNuWxt6zCswdQYDVR0jBG4wbIAUeKaXmmO1xaGlM7oifCNuWxt6zCuhSaRHMEUx
+// CzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRl
+// cm5ldCBXaWRnaXRzIFB0eSBMdGSCCQCxNRNlESDFkjAMBgNVHRMEBTADAQH/MA0G
+// CSqGSIb3DQEBBQUAA0EAhTZAc8G7GtrUWZ8tonAxRnTsg26oyDxRrzms7EC86CJG
+// HZnWRiok1IsFCEv7NRFukrt3uuQSu/TIXpyBqJdgTA==
// -----END CERTIFICATE-----
var rc4ClientScript = [][]byte{
{
@@ -210,3 +230,179 @@ var rc4ClientScript = [][]byte{
0x59, 0xac, 0xc6, 0xb5, 0x56, 0x55, 0x96,
},
}
+
+var ecdheAESClientScript = [][]byte{
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x4a, 0x01, 0x00, 0x00,
+ 0x46, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x13,
+ 0x01, 0x00, 0x00, 0x1b, 0x00, 0x05, 0x00, 0x05,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
+ 0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00,
+ 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x52, 0x02, 0x00, 0x00,
+ 0x4e, 0x03, 0x01, 0x50, 0xad, 0x72, 0xb1, 0x14,
+ 0x45, 0xce, 0x0a, 0x95, 0xf9, 0x63, 0xef, 0xa8,
+ 0xe5, 0x07, 0x34, 0x04, 0xe9, 0x08, 0x0f, 0x38,
+ 0xe4, 0x28, 0x27, 0x91, 0x07, 0x03, 0xe2, 0xfe,
+ 0xe3, 0x25, 0xf7, 0x20, 0x08, 0x42, 0xa2, 0x01,
+ 0x69, 0x53, 0xf0, 0xd9, 0x4c, 0xfa, 0x01, 0xa1,
+ 0xce, 0x4b, 0xf8, 0x28, 0x21, 0xad, 0x06, 0xbe,
+ 0xe0, 0x1b, 0x3b, 0xf7, 0xec, 0xd2, 0x52, 0xae,
+ 0x2a, 0x57, 0xb7, 0xa8, 0xc0, 0x13, 0x00, 0x00,
+ 0x06, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x16,
+ 0x03, 0x01, 0x02, 0x39, 0x0b, 0x00, 0x02, 0x35,
+ 0x00, 0x02, 0x32, 0x00, 0x02, 0x2f, 0x30, 0x82,
+ 0x02, 0x2b, 0x30, 0x82, 0x01, 0xd5, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xb1, 0x35,
+ 0x13, 0x65, 0x11, 0x20, 0xc5, 0x92, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+ 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+ 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+ 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+ 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
+ 0x31, 0x32, 0x30, 0x34, 0x30, 0x36, 0x31, 0x37,
+ 0x31, 0x30, 0x31, 0x33, 0x5a, 0x17, 0x0d, 0x31,
+ 0x35, 0x30, 0x34, 0x30, 0x36, 0x31, 0x37, 0x31,
+ 0x30, 0x31, 0x33, 0x5a, 0x30, 0x45, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
+ 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
+ 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
+ 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+ 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
+ 0x4c, 0x74, 0x64, 0x30, 0x5c, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30,
+ 0x48, 0x02, 0x41, 0x00, 0x9f, 0xb3, 0xc3, 0x84,
+ 0x27, 0x95, 0xff, 0x12, 0x31, 0x52, 0x0f, 0x15,
+ 0xef, 0x46, 0x11, 0xc4, 0xad, 0x80, 0xe6, 0x36,
+ 0x5b, 0x0f, 0xdd, 0x80, 0xd7, 0x61, 0x8d, 0xe0,
+ 0xfc, 0x72, 0x45, 0x09, 0x34, 0xfe, 0x55, 0x66,
+ 0x45, 0x43, 0x4c, 0x68, 0x97, 0x6a, 0xfe, 0xa8,
+ 0xa0, 0xa5, 0xdf, 0x5f, 0x78, 0xff, 0xee, 0xd7,
+ 0x64, 0xb8, 0x3f, 0x04, 0xcb, 0x6f, 0xff, 0x2a,
+ 0xfe, 0xfe, 0xb9, 0xed, 0x02, 0x03, 0x01, 0x00,
+ 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81, 0xa4, 0x30,
+ 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16,
+ 0x04, 0x14, 0x78, 0xa6, 0x97, 0x9a, 0x63, 0xb5,
+ 0xc5, 0xa1, 0xa5, 0x33, 0xba, 0x22, 0x7c, 0x23,
+ 0x6e, 0x5b, 0x1b, 0x7a, 0xcc, 0x2b, 0x30, 0x75,
+ 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x6e, 0x30,
+ 0x6c, 0x80, 0x14, 0x78, 0xa6, 0x97, 0x9a, 0x63,
+ 0xb5, 0xc5, 0xa1, 0xa5, 0x33, 0xba, 0x22, 0x7c,
+ 0x23, 0x6e, 0x5b, 0x1b, 0x7a, 0xcc, 0x2b, 0xa1,
+ 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31, 0x0b, 0x30,
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
+ 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d,
+ 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
+ 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
+ 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69,
+ 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c,
+ 0x74, 0x64, 0x82, 0x09, 0x00, 0xb1, 0x35, 0x13,
+ 0x65, 0x11, 0x20, 0xc5, 0x92, 0x30, 0x0c, 0x06,
+ 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03,
+ 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
+ 0x05, 0x00, 0x03, 0x41, 0x00, 0x85, 0x36, 0x40,
+ 0x73, 0xc1, 0xbb, 0x1a, 0xda, 0xd4, 0x59, 0x9f,
+ 0x2d, 0xa2, 0x70, 0x31, 0x46, 0x74, 0xec, 0x83,
+ 0x6e, 0xa8, 0xc8, 0x3c, 0x51, 0xaf, 0x39, 0xac,
+ 0xec, 0x40, 0xbc, 0xe8, 0x22, 0x46, 0x1d, 0x99,
+ 0xd6, 0x46, 0x2a, 0x24, 0xd4, 0x8b, 0x05, 0x08,
+ 0x4b, 0xfb, 0x35, 0x11, 0x6e, 0x92, 0xbb, 0x77,
+ 0xba, 0xe4, 0x12, 0xbb, 0xf4, 0xc8, 0x5e, 0x9c,
+ 0x81, 0xa8, 0x97, 0x60, 0x4c, 0x16, 0x03, 0x01,
+ 0x00, 0x8b, 0x0c, 0x00, 0x00, 0x87, 0x03, 0x00,
+ 0x17, 0x41, 0x04, 0x1c, 0x8f, 0x9c, 0x6d, 0xe7,
+ 0xab, 0x3e, 0xf8, 0x0a, 0x5d, 0xe1, 0x86, 0xb4,
+ 0xe2, 0x8e, 0xb2, 0x1c, 0x3b, 0xd9, 0xb6, 0x08,
+ 0x80, 0x58, 0x21, 0xe9, 0x0e, 0xc6, 0x66, 0x67,
+ 0x97, 0xcb, 0xb9, 0x92, 0x07, 0x00, 0xc4, 0xe5,
+ 0xec, 0x5f, 0xb4, 0xe2, 0x20, 0xa9, 0xc9, 0x62,
+ 0xd0, 0x98, 0xd5, 0xe3, 0x53, 0xff, 0xd0, 0x0a,
+ 0x6e, 0x29, 0x69, 0x39, 0x2a, 0x4b, 0x5c, 0xd8,
+ 0x6c, 0xf5, 0xfe, 0x00, 0x40, 0x35, 0xa7, 0x26,
+ 0x2e, 0xc2, 0x48, 0x93, 0x32, 0xf7, 0x7d, 0x0f,
+ 0x0d, 0x77, 0x56, 0x9a, 0x85, 0x0c, 0xa6, 0x74,
+ 0x06, 0xb8, 0x3d, 0x90, 0x56, 0x12, 0x63, 0xff,
+ 0x00, 0x5e, 0x0f, 0xf7, 0x24, 0xf7, 0xdb, 0x48,
+ 0x71, 0xe9, 0x2e, 0x03, 0xd3, 0xfa, 0x3a, 0xae,
+ 0xa0, 0xc1, 0x77, 0x3c, 0x4c, 0x59, 0xce, 0x33,
+ 0x1a, 0xd2, 0x47, 0x83, 0xfa, 0xea, 0xd8, 0x1e,
+ 0x06, 0xe7, 0x7d, 0xa0, 0x9b, 0x16, 0x03, 0x01,
+ 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x46, 0x10, 0x00, 0x00,
+ 0x42, 0x41, 0x04, 0x1e, 0x18, 0x37, 0xef, 0x0d,
+ 0x19, 0x51, 0x88, 0x35, 0x75, 0x71, 0xb5, 0xe5,
+ 0x54, 0x5b, 0x12, 0x2e, 0x8f, 0x09, 0x67, 0xfd,
+ 0xa7, 0x24, 0x20, 0x3e, 0xb2, 0x56, 0x1c, 0xce,
+ 0x97, 0x28, 0x5e, 0xf8, 0x2b, 0x2d, 0x4f, 0x9e,
+ 0xf1, 0x07, 0x9f, 0x6c, 0x4b, 0x5b, 0x83, 0x56,
+ 0xe2, 0x32, 0x42, 0xe9, 0x58, 0xb6, 0xd7, 0x49,
+ 0xa6, 0xb5, 0x68, 0x1a, 0x41, 0x03, 0x56, 0x6b,
+ 0xdc, 0x5a, 0x89, 0x14, 0x03, 0x01, 0x00, 0x01,
+ 0x01, 0x16, 0x03, 0x01, 0x00, 0x30, 0xd9, 0xa7,
+ 0x80, 0x56, 0x3f, 0xa3, 0x8f, 0x96, 0x72, 0x4e,
+ 0x4e, 0x6e, 0x23, 0x41, 0x8f, 0xda, 0x91, 0xb2,
+ 0x9e, 0x63, 0x23, 0x82, 0x64, 0xcd, 0x07, 0x24,
+ 0xd3, 0x40, 0x20, 0x22, 0x4c, 0xe3, 0xff, 0x38,
+ 0xbb, 0x43, 0x9d, 0x57, 0x11, 0xd5, 0x46, 0xa5,
+ 0x05, 0x29, 0x92, 0x02, 0xce, 0xdf,
+ },
+ {
+ 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+ 0x01, 0x00, 0x90, 0xe7, 0xba, 0x0e, 0xb1, 0xda,
+ 0x92, 0xb5, 0x77, 0x56, 0x38, 0xa6, 0x22, 0xc1,
+ 0x72, 0xeb, 0x8a, 0x68, 0x09, 0xb6, 0x74, 0xad,
+ 0xb3, 0x4a, 0xf2, 0xdd, 0x09, 0x9b, 0xc9, 0x4f,
+ 0x84, 0x73, 0x8b, 0xd6, 0x97, 0x50, 0x23, 0x1c,
+ 0xa0, 0xc2, 0x0c, 0x25, 0x18, 0xdd, 0x5e, 0x15,
+ 0x4d, 0xd9, 0xef, 0x4f, 0x6a, 0x43, 0x61, 0x9c,
+ 0x95, 0xde, 0x3c, 0x66, 0xc4, 0xc1, 0x33, 0x56,
+ 0xdd, 0x2f, 0x90, 0xaf, 0x68, 0x5c, 0x9c, 0xa4,
+ 0x90, 0x6d, 0xbf, 0x51, 0x1d, 0x68, 0xcb, 0x81,
+ 0x77, 0x52, 0xa0, 0x93, 0x2a, 0xf8, 0xc7, 0x61,
+ 0x87, 0x76, 0xca, 0x93, 0x9e, 0xd6, 0xee, 0x6f,
+ 0x3f, 0xeb, 0x7d, 0x06, 0xdd, 0x73, 0x4e, 0x27,
+ 0x16, 0x63, 0x92, 0xe4, 0xb2, 0x3f, 0x91, 0x23,
+ 0x21, 0x97, 0x90, 0xce, 0x53, 0xb8, 0xb0, 0x9d,
+ 0xbd, 0xbd, 0x33, 0x84, 0xad, 0x6b, 0x2e, 0x7b,
+ 0xf5, 0xeb, 0x1d, 0x64, 0x37, 0x2e, 0x29, 0x4e,
+ 0xb0, 0x93, 0xdb, 0x92, 0xc7, 0xaa, 0x94, 0xa5,
+ 0x3b, 0x64, 0xd0,
+ },
+ {
+ 0x17, 0x03, 0x01, 0x00, 0x20, 0x11, 0xd8, 0x6b,
+ 0x3c, 0xf6, 0xbe, 0xf4, 0x54, 0x87, 0xec, 0x75,
+ 0x0c, 0x44, 0xdb, 0x92, 0xfc, 0xde, 0x7e, 0x0f,
+ 0x9f, 0x87, 0x87, 0x9c, 0x03, 0xd5, 0x07, 0x84,
+ 0xe0, 0x3a, 0xf8, 0xae, 0x14, 0x17, 0x03, 0x01,
+ 0x00, 0x20, 0xba, 0x54, 0xef, 0x5b, 0xce, 0xfd,
+ 0x47, 0x76, 0x6d, 0xa1, 0x8b, 0xfd, 0x48, 0xde,
+ 0x6e, 0x26, 0xc1, 0x0c, 0x9d, 0x54, 0xbf, 0x98,
+ 0xf6, 0x1c, 0x80, 0xb9, 0xca, 0x93, 0x81, 0x0a,
+ 0x2e, 0x06, 0x15, 0x03, 0x01, 0x00, 0x20, 0x93,
+ 0x3e, 0x38, 0x17, 0xc9, 0x0a, 0xc3, 0xea, 0xd3,
+ 0x92, 0x75, 0xa6, 0x53, 0x37, 0x4d, 0x74, 0x94,
+ 0xbe, 0x01, 0xdc, 0x5c, 0x5a, 0x0f, 0x09, 0xf6,
+ 0x57, 0x33, 0xc3, 0xbc, 0x3f, 0x7a, 0x4d,
+ },
+}
diff --git a/src/pkg/crypto/tls/handshake_messages.go b/src/pkg/crypto/tls/handshake_messages.go
index 54c7a3e63..cdd491707 100644
--- a/src/pkg/crypto/tls/handshake_messages.go
+++ b/src/pkg/crypto/tls/handshake_messages.go
@@ -18,6 +18,8 @@ type clientHelloMsg struct {
ocspStapling bool
supportedCurves []uint16
supportedPoints []uint8
+ ticketSupported bool
+ sessionTicket []uint8
}
func (m *clientHelloMsg) equal(i interface{}) bool {
@@ -36,7 +38,9 @@ func (m *clientHelloMsg) equal(i interface{}) bool {
m.serverName == m1.serverName &&
m.ocspStapling == m1.ocspStapling &&
eqUint16s(m.supportedCurves, m1.supportedCurves) &&
- bytes.Equal(m.supportedPoints, m1.supportedPoints)
+ bytes.Equal(m.supportedPoints, m1.supportedPoints) &&
+ m.ticketSupported == m1.ticketSupported &&
+ bytes.Equal(m.sessionTicket, m1.sessionTicket)
}
func (m *clientHelloMsg) marshal() []byte {
@@ -66,6 +70,10 @@ func (m *clientHelloMsg) marshal() []byte {
extensionsLength += 1 + len(m.supportedPoints)
numExtensions++
}
+ if m.ticketSupported {
+ extensionsLength += len(m.sessionTicket)
+ numExtensions++
+ }
if numExtensions > 0 {
extensionsLength += 4 * numExtensions
length += 2 + extensionsLength
@@ -180,6 +188,17 @@ func (m *clientHelloMsg) marshal() []byte {
z = z[1:]
}
}
+ if m.ticketSupported {
+ // http://tools.ietf.org/html/rfc5077#section-3.2
+ z[0] = byte(extensionSessionTicket >> 8)
+ z[1] = byte(extensionSessionTicket)
+ l := len(m.sessionTicket)
+ z[2] = byte(l >> 8)
+ z[3] = byte(l)
+ z = z[4:]
+ copy(z, m.sessionTicket)
+ z = z[len(m.sessionTicket):]
+ }
m.raw = x
@@ -228,6 +247,8 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
m.nextProtoNeg = false
m.serverName = ""
m.ocspStapling = false
+ m.ticketSupported = false
+ m.sessionTicket = nil
if len(data) == 0 {
// ClientHello is optionally followed by extension data
@@ -311,6 +332,10 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
}
m.supportedPoints = make([]uint8, l)
copy(m.supportedPoints, data[1:])
+ case extensionSessionTicket:
+ // http://tools.ietf.org/html/rfc5077#section-3.2
+ m.ticketSupported = true
+ m.sessionTicket = data[:length]
}
data = data[length:]
}
@@ -328,6 +353,7 @@ type serverHelloMsg struct {
nextProtoNeg bool
nextProtos []string
ocspStapling bool
+ ticketSupported bool
}
func (m *serverHelloMsg) equal(i interface{}) bool {
@@ -344,7 +370,8 @@ func (m *serverHelloMsg) equal(i interface{}) bool {
m.compressionMethod == m1.compressionMethod &&
m.nextProtoNeg == m1.nextProtoNeg &&
eqStrings(m.nextProtos, m1.nextProtos) &&
- m.ocspStapling == m1.ocspStapling
+ m.ocspStapling == m1.ocspStapling &&
+ m.ticketSupported == m1.ticketSupported
}
func (m *serverHelloMsg) marshal() []byte {
@@ -368,6 +395,9 @@ func (m *serverHelloMsg) marshal() []byte {
if m.ocspStapling {
numExtensions++
}
+ if m.ticketSupported {
+ numExtensions++
+ }
if numExtensions > 0 {
extensionsLength += 4 * numExtensions
length += 2 + extensionsLength
@@ -416,6 +446,11 @@ func (m *serverHelloMsg) marshal() []byte {
z[1] = byte(extensionStatusRequest)
z = z[4:]
}
+ if m.ticketSupported {
+ z[0] = byte(extensionSessionTicket >> 8)
+ z[1] = byte(extensionSessionTicket)
+ z = z[4:]
+ }
m.raw = x
@@ -445,6 +480,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
m.nextProtoNeg = false
m.nextProtos = nil
m.ocspStapling = false
+ m.ticketSupported = false
if len(data) == 0 {
// ServerHello is optionally followed by extension data
@@ -474,14 +510,14 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
switch extension {
case extensionNextProtoNeg:
m.nextProtoNeg = true
- d := data
+ d := data[:length]
for len(d) > 0 {
l := int(d[0])
d = d[1:]
if l == 0 || l > len(d) {
return false
}
- m.nextProtos = append(m.nextProtos, string(d[0:l]))
+ m.nextProtos = append(m.nextProtos, string(d[:l]))
d = d[l:]
}
case extensionStatusRequest:
@@ -489,6 +525,11 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
return false
}
m.ocspStapling = true
+ case extensionSessionTicket:
+ if length > 0 {
+ return false
+ }
+ m.ticketSupported = true
}
data = data[length:]
}
@@ -1030,6 +1071,65 @@ func (m *certificateVerifyMsg) unmarshal(data []byte) bool {
return true
}
+type newSessionTicketMsg struct {
+ raw []byte
+ ticket []byte
+}
+
+func (m *newSessionTicketMsg) equal(i interface{}) bool {
+ m1, ok := i.(*newSessionTicketMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ bytes.Equal(m.ticket, m1.ticket)
+}
+
+func (m *newSessionTicketMsg) marshal() (x []byte) {
+ if m.raw != nil {
+ return m.raw
+ }
+
+ // See http://tools.ietf.org/html/rfc5077#section-3.3
+ ticketLen := len(m.ticket)
+ length := 2 + 4 + ticketLen
+ x = make([]byte, 4+length)
+ x[0] = typeNewSessionTicket
+ x[1] = uint8(length >> 16)
+ x[2] = uint8(length >> 8)
+ x[3] = uint8(length)
+ x[8] = uint8(ticketLen >> 8)
+ x[9] = uint8(ticketLen)
+ copy(x[10:], m.ticket)
+
+ m.raw = x
+
+ return
+}
+
+func (m *newSessionTicketMsg) unmarshal(data []byte) bool {
+ m.raw = data
+
+ if len(data) < 10 {
+ return false
+ }
+
+ length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
+ if uint32(len(data))-4 != length {
+ return false
+ }
+
+ ticketLen := int(data[8])<<8 + int(data[9])
+ if len(data)-10 != ticketLen {
+ return false
+ }
+
+ m.ticket = data[10:]
+
+ return true
+}
+
func eqUint16s(x, y []uint16) bool {
if len(x) != len(y) {
return false
diff --git a/src/pkg/crypto/tls/handshake_messages_test.go b/src/pkg/crypto/tls/handshake_messages_test.go
index e62a9d581..3434bad9f 100644
--- a/src/pkg/crypto/tls/handshake_messages_test.go
+++ b/src/pkg/crypto/tls/handshake_messages_test.go
@@ -22,6 +22,8 @@ var tests = []interface{}{
&certificateStatusMsg{},
&clientKeyExchangeMsg{},
&nextProtoMsg{},
+ &newSessionTicketMsg{},
+ &sessionState{},
}
type testMessage interface {
@@ -127,6 +129,12 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
for i := range m.supportedCurves {
m.supportedCurves[i] = uint16(rand.Intn(30000))
}
+ if rand.Intn(10) > 5 {
+ m.ticketSupported = true
+ if rand.Intn(10) > 5 {
+ m.sessionTicket = randomBytes(rand.Intn(300), rand)
+ }
+ }
return reflect.ValueOf(m)
}
@@ -149,6 +157,13 @@ func (*serverHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
}
}
+ if rand.Intn(10) > 5 {
+ m.ocspStapling = true
+ }
+ if rand.Intn(10) > 5 {
+ m.ticketSupported = true
+ }
+
return reflect.ValueOf(m)
}
@@ -207,3 +222,22 @@ func (*nextProtoMsg) Generate(rand *rand.Rand, size int) reflect.Value {
m.proto = randomString(rand.Intn(255), rand)
return reflect.ValueOf(m)
}
+
+func (*newSessionTicketMsg) Generate(rand *rand.Rand, size int) reflect.Value {
+ m := &newSessionTicketMsg{}
+ m.ticket = randomBytes(rand.Intn(4), rand)
+ return reflect.ValueOf(m)
+}
+
+func (*sessionState) Generate(rand *rand.Rand, size int) reflect.Value {
+ s := &sessionState{}
+ s.vers = uint16(rand.Intn(10000))
+ s.cipherSuite = uint16(rand.Intn(10000))
+ s.masterSecret = randomBytes(rand.Intn(100), rand)
+ numCerts := rand.Intn(20)
+ s.certificates = make([][]byte, numCerts)
+ for i := 0; i < numCerts; i++ {
+ s.certificates[i] = randomBytes(rand.Intn(10)+1, rand)
+ }
+ return reflect.ValueOf(s)
+}
diff --git a/src/pkg/crypto/tls/handshake_server.go b/src/pkg/crypto/tls/handshake_server.go
index 76adc540c..730991016 100644
--- a/src/pkg/crypto/tls/handshake_server.go
+++ b/src/pkg/crypto/tls/handshake_server.go
@@ -13,31 +13,120 @@ import (
"io"
)
+// serverHandshakeState contains details of a server handshake in progress.
+// It's discarded once the handshake has completed.
+type serverHandshakeState struct {
+ c *Conn
+ clientHello *clientHelloMsg
+ hello *serverHelloMsg
+ suite *cipherSuite
+ ellipticOk bool
+ sessionState *sessionState
+ finishedHash finishedHash
+ masterSecret []byte
+ certsFromClient [][]byte
+}
+
+// serverHandshake performs a TLS handshake as a server.
func (c *Conn) serverHandshake() error {
config := c.config
- msg, err := c.readHandshake()
+
+ // If this is the first server handshake, we generate a random key to
+ // encrypt the tickets with.
+ config.serverInitOnce.Do(func() {
+ if config.SessionTicketsDisabled {
+ return
+ }
+
+ // If the key has already been set then we have nothing to do.
+ for _, b := range config.SessionTicketKey {
+ if b != 0 {
+ return
+ }
+ }
+
+ if _, err := io.ReadFull(config.rand(), config.SessionTicketKey[:]); err != nil {
+ config.SessionTicketsDisabled = true
+ }
+ })
+
+ hs := serverHandshakeState{
+ c: c,
+ }
+ isResume, err := hs.readClientHello()
if err != nil {
return err
}
- clientHello, ok := msg.(*clientHelloMsg)
+
+ // For an overview of TLS handshaking, see https://tools.ietf.org/html/rfc5246#section-7.3
+ if isResume {
+ // The client has included a session ticket and so we do an abbreviated handshake.
+ if err := hs.doResumeHandshake(); err != nil {
+ return err
+ }
+ if err := hs.establishKeys(); err != nil {
+ return err
+ }
+ if err := hs.sendFinished(); err != nil {
+ return err
+ }
+ if err := hs.readFinished(); err != nil {
+ return err
+ }
+ c.didResume = true
+ } else {
+ // The client didn't include a session ticket, or it wasn't
+ // valid so we do a full handshake.
+ if err := hs.doFullHandshake(); err != nil {
+ return err
+ }
+ if err := hs.establishKeys(); err != nil {
+ return err
+ }
+ if err := hs.readFinished(); err != nil {
+ return err
+ }
+ if err := hs.sendSessionTicket(); err != nil {
+ return err
+ }
+ if err := hs.sendFinished(); err != nil {
+ return err
+ }
+ }
+ c.handshakeComplete = true
+
+ return nil
+}
+
+// readClientHello reads a ClientHello message from the client and decides
+// whether we will perform session resumption.
+func (hs *serverHandshakeState) readClientHello() (isResume bool, err error) {
+ config := hs.c.config
+ c := hs.c
+
+ msg, err := c.readHandshake()
+ if err != nil {
+ return false, err
+ }
+ var ok bool
+ hs.clientHello, ok = msg.(*clientHelloMsg)
if !ok {
- return c.sendAlert(alertUnexpectedMessage)
+ return false, c.sendAlert(alertUnexpectedMessage)
}
- vers, ok := mutualVersion(clientHello.vers)
+ c.vers, ok = mutualVersion(hs.clientHello.vers)
if !ok {
- return c.sendAlert(alertProtocolVersion)
+ return false, c.sendAlert(alertProtocolVersion)
}
- c.vers = vers
c.haveVers = true
- finishedHash := newFinishedHash(vers)
- finishedHash.Write(clientHello.marshal())
+ hs.finishedHash = newFinishedHash(c.vers)
+ hs.finishedHash.Write(hs.clientHello.marshal())
- hello := new(serverHelloMsg)
+ hs.hello = new(serverHelloMsg)
supportedCurve := false
Curves:
- for _, curve := range clientHello.supportedCurves {
+ for _, curve := range hs.clientHello.supportedCurves {
switch curve {
case curveP256, curveP384, curveP521:
supportedCurve = true
@@ -46,110 +135,182 @@ Curves:
}
supportedPointFormat := false
- for _, pointFormat := range clientHello.supportedPoints {
+ for _, pointFormat := range hs.clientHello.supportedPoints {
if pointFormat == pointFormatUncompressed {
supportedPointFormat = true
break
}
}
-
- ellipticOk := supportedCurve && supportedPointFormat
-
- var suite *cipherSuite
-FindCipherSuite:
- for _, id := range clientHello.cipherSuites {
- for _, supported := range config.cipherSuites() {
- if id == supported {
- var candidate *cipherSuite
-
- for _, s := range cipherSuites {
- if s.id == id {
- candidate = s
- break
- }
- }
- if candidate == nil {
- continue
- }
- // Don't select a ciphersuite which we can't
- // support for this client.
- if candidate.elliptic && !ellipticOk {
- continue
- }
- suite = candidate
- break FindCipherSuite
- }
- }
- }
+ hs.ellipticOk = supportedCurve && supportedPointFormat
foundCompression := false
// We only support null compression, so check that the client offered it.
- for _, compression := range clientHello.compressionMethods {
+ for _, compression := range hs.clientHello.compressionMethods {
if compression == compressionNone {
foundCompression = true
break
}
}
- if suite == nil || !foundCompression {
- return c.sendAlert(alertHandshakeFailure)
+ if !foundCompression {
+ return false, c.sendAlert(alertHandshakeFailure)
}
- hello.vers = vers
- hello.cipherSuite = suite.id
+ hs.hello.vers = c.vers
t := uint32(config.time().Unix())
- hello.random = make([]byte, 32)
- hello.random[0] = byte(t >> 24)
- hello.random[1] = byte(t >> 16)
- hello.random[2] = byte(t >> 8)
- hello.random[3] = byte(t)
- _, err = io.ReadFull(config.rand(), hello.random[4:])
+ hs.hello.random = make([]byte, 32)
+ hs.hello.random[0] = byte(t >> 24)
+ hs.hello.random[1] = byte(t >> 16)
+ hs.hello.random[2] = byte(t >> 8)
+ hs.hello.random[3] = byte(t)
+ _, err = io.ReadFull(config.rand(), hs.hello.random[4:])
if err != nil {
- return c.sendAlert(alertInternalError)
+ return false, c.sendAlert(alertInternalError)
+ }
+ hs.hello.compressionMethod = compressionNone
+ if len(hs.clientHello.serverName) > 0 {
+ c.serverName = hs.clientHello.serverName
+ }
+ if hs.clientHello.nextProtoNeg {
+ hs.hello.nextProtoNeg = true
+ hs.hello.nextProtos = config.NextProtos
+ }
+
+ if hs.checkForResumption() {
+ return true, nil
+ }
+
+ var preferenceList, supportedList []uint16
+ if c.config.PreferServerCipherSuites {
+ preferenceList = c.config.cipherSuites()
+ supportedList = hs.clientHello.cipherSuites
+ } else {
+ preferenceList = hs.clientHello.cipherSuites
+ supportedList = c.config.cipherSuites()
+ }
+
+ for _, id := range preferenceList {
+ if hs.suite = c.tryCipherSuite(id, supportedList, hs.ellipticOk); hs.suite != nil {
+ break
+ }
+ }
+
+ if hs.suite == nil {
+ return false, c.sendAlert(alertHandshakeFailure)
+ }
+
+ return false, nil
+}
+
+// checkForResumption returns true if we should perform resumption on this connection.
+func (hs *serverHandshakeState) checkForResumption() bool {
+ c := hs.c
+
+ var ok bool
+ if hs.sessionState, ok = c.decryptTicket(hs.clientHello.sessionTicket); !ok {
+ return false
}
- hello.compressionMethod = compressionNone
- if clientHello.nextProtoNeg {
- hello.nextProtoNeg = true
- hello.nextProtos = config.NextProtos
+
+ if hs.sessionState.vers > hs.clientHello.vers {
+ return false
+ }
+ if vers, ok := mutualVersion(hs.sessionState.vers); !ok || vers != hs.sessionState.vers {
+ return false
+ }
+
+ cipherSuiteOk := false
+ // Check that the client is still offering the ciphersuite in the session.
+ for _, id := range hs.clientHello.cipherSuites {
+ if id == hs.sessionState.cipherSuite {
+ cipherSuiteOk = true
+ break
+ }
+ }
+ if !cipherSuiteOk {
+ return false
+ }
+
+ // Check that we also support the ciphersuite from the session.
+ hs.suite = c.tryCipherSuite(hs.sessionState.cipherSuite, c.config.cipherSuites(), hs.ellipticOk)
+ if hs.suite == nil {
+ return false
+ }
+
+ sessionHasClientCerts := len(hs.sessionState.certificates) != 0
+ needClientCerts := c.config.ClientAuth == RequireAnyClientCert || c.config.ClientAuth == RequireAndVerifyClientCert
+ if needClientCerts && !sessionHasClientCerts {
+ return false
+ }
+ if sessionHasClientCerts && c.config.ClientAuth == NoClientCert {
+ return false
}
+ return true
+}
+
+func (hs *serverHandshakeState) doResumeHandshake() error {
+ c := hs.c
+
+ hs.hello.cipherSuite = hs.suite.id
+ // We echo the client's session ID in the ServerHello to let it know
+ // that we're doing a resumption.
+ hs.hello.sessionId = hs.clientHello.sessionId
+ hs.finishedHash.Write(hs.hello.marshal())
+ c.writeRecord(recordTypeHandshake, hs.hello.marshal())
+
+ if len(hs.sessionState.certificates) > 0 {
+ if _, err := hs.processCertsFromClient(hs.sessionState.certificates); err != nil {
+ return err
+ }
+ }
+
+ hs.masterSecret = hs.sessionState.masterSecret
+
+ return nil
+}
+
+func (hs *serverHandshakeState) doFullHandshake() error {
+ config := hs.c.config
+ c := hs.c
+
if len(config.Certificates) == 0 {
return c.sendAlert(alertInternalError)
}
cert := &config.Certificates[0]
- if len(clientHello.serverName) > 0 {
- c.serverName = clientHello.serverName
- cert = config.getCertificateForName(clientHello.serverName)
+ if len(hs.clientHello.serverName) > 0 {
+ cert = config.getCertificateForName(hs.clientHello.serverName)
}
- if clientHello.ocspStapling && len(cert.OCSPStaple) > 0 {
- hello.ocspStapling = true
+ if hs.clientHello.ocspStapling && len(cert.OCSPStaple) > 0 {
+ hs.hello.ocspStapling = true
}
- finishedHash.Write(hello.marshal())
- c.writeRecord(recordTypeHandshake, hello.marshal())
+ hs.hello.ticketSupported = hs.clientHello.ticketSupported && !config.SessionTicketsDisabled
+ hs.hello.cipherSuite = hs.suite.id
+ hs.finishedHash.Write(hs.hello.marshal())
+ c.writeRecord(recordTypeHandshake, hs.hello.marshal())
certMsg := new(certificateMsg)
certMsg.certificates = cert.Certificate
- finishedHash.Write(certMsg.marshal())
+ hs.finishedHash.Write(certMsg.marshal())
c.writeRecord(recordTypeHandshake, certMsg.marshal())
- if hello.ocspStapling {
+ if hs.hello.ocspStapling {
certStatus := new(certificateStatusMsg)
certStatus.statusType = statusTypeOCSP
certStatus.response = cert.OCSPStaple
- finishedHash.Write(certStatus.marshal())
+ hs.finishedHash.Write(certStatus.marshal())
c.writeRecord(recordTypeHandshake, certStatus.marshal())
}
- keyAgreement := suite.ka()
- skx, err := keyAgreement.generateServerKeyExchange(config, cert, clientHello, hello)
+ keyAgreement := hs.suite.ka()
+ skx, err := keyAgreement.generateServerKeyExchange(config, cert, hs.clientHello, hs.hello)
if err != nil {
c.sendAlert(alertHandshakeFailure)
return err
}
if skx != nil {
- finishedHash.Write(skx.marshal())
+ hs.finishedHash.Write(skx.marshal())
c.writeRecord(recordTypeHandshake, skx.marshal())
}
@@ -166,28 +327,29 @@ FindCipherSuite:
if config.ClientCAs != nil {
certReq.certificateAuthorities = config.ClientCAs.Subjects()
}
- finishedHash.Write(certReq.marshal())
+ hs.finishedHash.Write(certReq.marshal())
c.writeRecord(recordTypeHandshake, certReq.marshal())
}
helloDone := new(serverHelloDoneMsg)
- finishedHash.Write(helloDone.marshal())
+ hs.finishedHash.Write(helloDone.marshal())
c.writeRecord(recordTypeHandshake, helloDone.marshal())
var pub *rsa.PublicKey // public key for client auth, if any
- msg, err = c.readHandshake()
+ msg, err := c.readHandshake()
if err != nil {
return err
}
+ var ok bool
// If we requested a client certificate, then the client must send a
// certificate message, even if it's empty.
if config.ClientAuth >= RequestClientCert {
if certMsg, ok = msg.(*certificateMsg); !ok {
return c.sendAlert(alertHandshakeFailure)
}
- finishedHash.Write(certMsg.marshal())
+ hs.finishedHash.Write(certMsg.marshal())
if len(certMsg.certificates) == 0 {
// The client didn't actually send a certificate
@@ -198,54 +360,9 @@ FindCipherSuite:
}
}
- certs := make([]*x509.Certificate, len(certMsg.certificates))
- for i, asn1Data := range certMsg.certificates {
- if certs[i], err = x509.ParseCertificate(asn1Data); err != nil {
- c.sendAlert(alertBadCertificate)
- return errors.New("tls: failed to parse client certificate: " + err.Error())
- }
- }
-
- if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
- opts := x509.VerifyOptions{
- Roots: c.config.ClientCAs,
- CurrentTime: c.config.time(),
- Intermediates: x509.NewCertPool(),
- }
-
- for i, cert := range certs {
- if i == 0 {
- continue
- }
- opts.Intermediates.AddCert(cert)
- }
-
- chains, err := certs[0].Verify(opts)
- if err != nil {
- c.sendAlert(alertBadCertificate)
- return errors.New("tls: failed to verify client's certificate: " + err.Error())
- }
-
- ok := false
- for _, ku := range certs[0].ExtKeyUsage {
- if ku == x509.ExtKeyUsageClientAuth {
- ok = true
- break
- }
- }
- if !ok {
- c.sendAlert(alertHandshakeFailure)
- return errors.New("tls: client's certificate's extended key usage doesn't permit it to be used for client authentication")
- }
-
- c.verifiedChains = chains
- }
-
- if len(certs) > 0 {
- if pub, ok = certs[0].PublicKey.(*rsa.PublicKey); !ok {
- return c.sendAlert(alertUnsupportedCertificate)
- }
- c.peerCertificates = certs
+ pub, err = hs.processCertsFromClient(certMsg.certificates)
+ if err != nil {
+ return err
}
msg, err = c.readHandshake()
@@ -259,7 +376,7 @@ FindCipherSuite:
if !ok {
return c.sendAlert(alertUnexpectedMessage)
}
- finishedHash.Write(ckx.marshal())
+ hs.finishedHash.Write(ckx.marshal())
// If we received a client cert in response to our certificate request message,
// the client will send us a certificateVerifyMsg immediately after the
@@ -278,15 +395,15 @@ FindCipherSuite:
}
digest := make([]byte, 0, 36)
- digest = finishedHash.serverMD5.Sum(digest)
- digest = finishedHash.serverSHA1.Sum(digest)
+ digest = hs.finishedHash.serverMD5.Sum(digest)
+ digest = hs.finishedHash.serverSHA1.Sum(digest)
err = rsa.VerifyPKCS1v15(pub, crypto.MD5SHA1, digest, certVerify.signature)
if err != nil {
c.sendAlert(alertBadCertificate)
return errors.New("could not validate signature of connection nonces: " + err.Error())
}
- finishedHash.Write(certVerify.marshal())
+ hs.finishedHash.Write(certVerify.marshal())
}
preMasterSecret, err := keyAgreement.processClientKeyExchange(config, cert, ckx, c.vers)
@@ -294,20 +411,38 @@ FindCipherSuite:
c.sendAlert(alertHandshakeFailure)
return err
}
+ hs.masterSecret = masterFromPreMasterSecret(c.vers, preMasterSecret, hs.clientHello.random, hs.hello.random)
+
+ return nil
+}
+
+func (hs *serverHandshakeState) establishKeys() error {
+ c := hs.c
- masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
- keysFromPreMasterSecret(c.vers, preMasterSecret, clientHello.random, hello.random, suite.macLen, suite.keyLen, suite.ivLen)
+ clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
+ keysFromMasterSecret(c.vers, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
- clientCipher := suite.cipher(clientKey, clientIV, true /* for reading */)
- clientHash := suite.mac(c.vers, clientMAC)
+ clientCipher := hs.suite.cipher(clientKey, clientIV, true /* for reading */)
+ clientHash := hs.suite.mac(c.vers, clientMAC)
c.in.prepareCipherSpec(c.vers, clientCipher, clientHash)
+
+ serverCipher := hs.suite.cipher(serverKey, serverIV, false /* not for reading */)
+ serverHash := hs.suite.mac(c.vers, serverMAC)
+ c.out.prepareCipherSpec(c.vers, serverCipher, serverHash)
+
+ return nil
+}
+
+func (hs *serverHandshakeState) readFinished() error {
+ c := hs.c
+
c.readRecord(recordTypeChangeCipherSpec)
if err := c.error(); err != nil {
return err
}
- if hello.nextProtoNeg {
- msg, err = c.readHandshake()
+ if hs.hello.nextProtoNeg {
+ msg, err := c.readHandshake()
if err != nil {
return err
}
@@ -315,11 +450,11 @@ FindCipherSuite:
if !ok {
return c.sendAlert(alertUnexpectedMessage)
}
- finishedHash.Write(nextProto.marshal())
+ hs.finishedHash.Write(nextProto.marshal())
c.clientProtocol = nextProto.proto
}
- msg, err = c.readHandshake()
+ msg, err := c.readHandshake()
if err != nil {
return err
}
@@ -328,25 +463,142 @@ FindCipherSuite:
return c.sendAlert(alertUnexpectedMessage)
}
- verify := finishedHash.clientSum(masterSecret)
+ verify := hs.finishedHash.clientSum(hs.masterSecret)
if len(verify) != len(clientFinished.verifyData) ||
subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 {
return c.sendAlert(alertHandshakeFailure)
}
- finishedHash.Write(clientFinished.marshal())
+ hs.finishedHash.Write(clientFinished.marshal())
+ return nil
+}
+
+func (hs *serverHandshakeState) sendSessionTicket() error {
+ if !hs.hello.ticketSupported {
+ return nil
+ }
+
+ c := hs.c
+ m := new(newSessionTicketMsg)
+
+ var err error
+ state := sessionState{
+ vers: c.vers,
+ cipherSuite: hs.suite.id,
+ masterSecret: hs.masterSecret,
+ certificates: hs.certsFromClient,
+ }
+ m.ticket, err = c.encryptTicket(&state)
+ if err != nil {
+ return err
+ }
+
+ hs.finishedHash.Write(m.marshal())
+ c.writeRecord(recordTypeHandshake, m.marshal())
+
+ return nil
+}
+
+func (hs *serverHandshakeState) sendFinished() error {
+ c := hs.c
- serverCipher := suite.cipher(serverKey, serverIV, false /* not for reading */)
- serverHash := suite.mac(c.vers, serverMAC)
- c.out.prepareCipherSpec(c.vers, serverCipher, serverHash)
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
finished := new(finishedMsg)
- finished.verifyData = finishedHash.serverSum(masterSecret)
+ finished.verifyData = hs.finishedHash.serverSum(hs.masterSecret)
+ hs.finishedHash.Write(finished.marshal())
c.writeRecord(recordTypeHandshake, finished.marshal())
- c.handshakeComplete = true
- c.cipherSuite = suite.id
+ c.cipherSuite = hs.suite.id
+
+ return nil
+}
+
+// processCertsFromClient takes a chain of client certificates either from a
+// Certificates message or from a sessionState and verifies them. It returns
+// the public key of the leaf certificate.
+func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (*rsa.PublicKey, error) {
+ c := hs.c
+
+ hs.certsFromClient = certificates
+ certs := make([]*x509.Certificate, len(certificates))
+ var err error
+ for i, asn1Data := range certificates {
+ if certs[i], err = x509.ParseCertificate(asn1Data); err != nil {
+ c.sendAlert(alertBadCertificate)
+ return nil, errors.New("tls: failed to parse client certificate: " + err.Error())
+ }
+ }
+
+ if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
+ opts := x509.VerifyOptions{
+ Roots: c.config.ClientCAs,
+ CurrentTime: c.config.time(),
+ Intermediates: x509.NewCertPool(),
+ KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
+ }
+
+ for _, cert := range certs[1:] {
+ opts.Intermediates.AddCert(cert)
+ }
+
+ chains, err := certs[0].Verify(opts)
+ if err != nil {
+ c.sendAlert(alertBadCertificate)
+ return nil, errors.New("tls: failed to verify client's certificate: " + err.Error())
+ }
+
+ ok := false
+ for _, ku := range certs[0].ExtKeyUsage {
+ if ku == x509.ExtKeyUsageClientAuth {
+ ok = true
+ break
+ }
+ }
+ if !ok {
+ c.sendAlert(alertHandshakeFailure)
+ return nil, errors.New("tls: client's certificate's extended key usage doesn't permit it to be used for client authentication")
+ }
+
+ c.verifiedChains = chains
+ }
+
+ if len(certs) > 0 {
+ pub, ok := certs[0].PublicKey.(*rsa.PublicKey)
+ if !ok {
+ return nil, c.sendAlert(alertUnsupportedCertificate)
+ }
+ c.peerCertificates = certs
+ return pub, nil
+ }
+
+ return nil, nil
+}
+
+// tryCipherSuite returns a cipherSuite with the given id if that cipher suite
+// is acceptable to use.
+func (c *Conn) tryCipherSuite(id uint16, supportedCipherSuites []uint16, ellipticOk bool) *cipherSuite {
+ for _, supported := range supportedCipherSuites {
+ if id == supported {
+ var candidate *cipherSuite
+
+ for _, s := range cipherSuites {
+ if s.id == id {
+ candidate = s
+ break
+ }
+ }
+ if candidate == nil {
+ continue
+ }
+ // Don't select a ciphersuite which we can't
+ // support for this client.
+ if candidate.elliptic && !ellipticOk {
+ continue
+ }
+ return candidate
+ }
+ }
return nil
}
diff --git a/src/pkg/crypto/tls/handshake_server_test.go b/src/pkg/crypto/tls/handshake_server_test.go
index 7c1267101..bf8cbe3ae 100644
--- a/src/pkg/crypto/tls/handshake_server_test.go
+++ b/src/pkg/crypto/tls/handshake_server_test.go
@@ -11,12 +11,15 @@ import (
"encoding/hex"
"encoding/pem"
"flag"
+ "fmt"
"io"
"log"
"math/big"
"net"
+ "os"
"strconv"
"strings"
+ "sync"
"testing"
"time"
)
@@ -80,13 +83,20 @@ func TestRejectBadProtocolVersion(t *testing.T) {
}
func TestNoSuiteOverlap(t *testing.T) {
- clientHello := &clientHelloMsg{nil, 0x0301, nil, nil, []uint16{0xff00}, []uint8{0}, false, "", false, nil, nil}
+ clientHello := &clientHelloMsg{
+ vers: 0x0301,
+ cipherSuites: []uint16{0xff00},
+ compressionMethods: []uint8{0},
+ }
testClientHelloFailure(t, clientHello, alertHandshakeFailure)
-
}
func TestNoCompressionOverlap(t *testing.T) {
- clientHello := &clientHelloMsg{nil, 0x0301, nil, nil, []uint16{TLS_RSA_WITH_RC4_128_SHA}, []uint8{0xff}, false, "", false, nil, nil}
+ clientHello := &clientHelloMsg{
+ vers: 0x0301,
+ cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ compressionMethods: []uint8{0xff},
+ }
testClientHelloFailure(t, clientHello, alertHandshakeFailure)
}
@@ -115,6 +125,50 @@ func TestClose(t *testing.T) {
}
}
+func testHandshake(clientConfig, serverConfig *Config) (state ConnectionState, err error) {
+ c, s := net.Pipe()
+ go func() {
+ cli := Client(c, clientConfig)
+ cli.Handshake()
+ c.Close()
+ }()
+ server := Server(s, serverConfig)
+ err = server.Handshake()
+ if err == nil {
+ state = server.ConnectionState()
+ }
+ s.Close()
+ return
+}
+
+func TestCipherSuitePreference(t *testing.T) {
+ serverConfig := &Config{
+ CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA},
+ Certificates: testConfig.Certificates,
+ }
+ clientConfig := &Config{
+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_RC4_128_SHA},
+ InsecureSkipVerify: true,
+ }
+ state, err := testHandshake(clientConfig, serverConfig)
+ if err != nil {
+ t.Fatalf("handshake failed: %s", err)
+ }
+ if state.CipherSuite != TLS_RSA_WITH_AES_128_CBC_SHA {
+ // By default the server should use the client's preference.
+ t.Fatalf("Client's preference was not used, got %x", state.CipherSuite)
+ }
+
+ serverConfig.PreferServerCipherSuites = true
+ state, err = testHandshake(clientConfig, serverConfig)
+ if err != nil {
+ t.Fatalf("handshake failed: %s", err)
+ }
+ if state.CipherSuite != TLS_RSA_WITH_RC4_128_SHA {
+ t.Fatalf("Server's preference was not used, got %x", state.CipherSuite)
+ }
+}
+
func testServerScript(t *testing.T, name string, serverScript [][]byte, config *Config, peers []*x509.Certificate) {
c, s := net.Pipe()
srv := Server(s, config)
@@ -186,6 +240,11 @@ func TestHandshakeServerSNI(t *testing.T) {
testServerScript(t, "SNI", selectCertificateBySNIScript, testConfig, nil)
}
+func TestResumption(t *testing.T) {
+ testServerScript(t, "IssueTicket", issueSessionTicketTest, testConfig, nil)
+ testServerScript(t, "Resume", serverResumeTest, testConfig, nil)
+}
+
type clientauthTest struct {
name string
clientauth ClientAuthType
@@ -203,55 +262,133 @@ func TestClientAuth(t *testing.T) {
}
}
+// recordingConn is a net.Conn that records the traffic that passes through it.
+// WriteTo can be used to produce Go code that contains the recorded traffic.
+type recordingConn struct {
+ net.Conn
+ lock sync.Mutex
+ flows [][]byte
+ currentlyReading bool
+}
+
+func (r *recordingConn) Read(b []byte) (n int, err error) {
+ if n, err = r.Conn.Read(b); n == 0 {
+ return
+ }
+ b = b[:n]
+
+ r.lock.Lock()
+ defer r.lock.Unlock()
+
+ if l := len(r.flows); l == 0 || !r.currentlyReading {
+ buf := make([]byte, len(b))
+ copy(buf, b)
+ r.flows = append(r.flows, buf)
+ } else {
+ r.flows[l-1] = append(r.flows[l-1], b[:n]...)
+ }
+ r.currentlyReading = true
+ return
+}
+
+func (r *recordingConn) Write(b []byte) (n int, err error) {
+ if n, err = r.Conn.Write(b); n == 0 {
+ return
+ }
+ b = b[:n]
+
+ r.lock.Lock()
+ defer r.lock.Unlock()
+
+ if l := len(r.flows); l == 0 || r.currentlyReading {
+ buf := make([]byte, len(b))
+ copy(buf, b)
+ r.flows = append(r.flows, buf)
+ } else {
+ r.flows[l-1] = append(r.flows[l-1], b[:n]...)
+ }
+ r.currentlyReading = false
+ return
+}
+
+// WriteTo writes Go source code to w that contains the recorded traffic.
+func (r *recordingConn) WriteTo(w io.Writer) {
+ fmt.Fprintf(w, "var changeMe = [][]byte {\n")
+ for _, buf := range r.flows {
+ fmt.Fprintf(w, "\t{")
+ for i, b := range buf {
+ if i%8 == 0 {
+ fmt.Fprintf(w, "\n\t\t")
+ }
+ fmt.Fprintf(w, "0x%02x, ", b)
+ }
+ fmt.Fprintf(w, "\n\t},\n")
+ }
+ fmt.Fprintf(w, "}\n")
+}
+
var serve = flag.Bool("serve", false, "run a TLS server on :10443")
var testCipherSuites = flag.String("ciphersuites",
"0x"+strconv.FormatInt(int64(TLS_RSA_WITH_RC4_128_SHA), 16),
"cipher suites to accept in serving mode")
var testClientAuth = flag.Int("clientauth", 0, "value for tls.Config.ClientAuth")
-func TestRunServer(t *testing.T) {
- if !*serve {
- return
- }
-
+func GetTestConfig() *Config {
+ var config = *testConfig
suites := strings.Split(*testCipherSuites, ",")
- testConfig.CipherSuites = make([]uint16, len(suites))
+ config.CipherSuites = make([]uint16, len(suites))
for i := range suites {
suite, err := strconv.ParseUint(suites[i], 0, 64)
if err != nil {
panic(err)
}
- testConfig.CipherSuites[i] = uint16(suite)
+ config.CipherSuites[i] = uint16(suite)
}
- testConfig.ClientAuth = ClientAuthType(*testClientAuth)
+ config.ClientAuth = ClientAuthType(*testClientAuth)
+ return &config
+}
+
+func TestRunServer(t *testing.T) {
+ if !*serve {
+ return
+ }
+
+ config := GetTestConfig()
- l, err := Listen("tcp", ":10443", testConfig)
+ const addr = ":10443"
+ l, err := net.Listen("tcp", addr)
if err != nil {
t.Fatal(err)
}
+ log.Printf("Now listening for connections on %s", addr)
for {
- c, err := l.Accept()
+ tcpConn, err := l.Accept()
if err != nil {
+ log.Printf("error accepting connection: %s", err)
+ break
+ }
+
+ record := &recordingConn{
+ Conn: tcpConn,
+ }
+
+ conn := Server(record, config)
+ if err := conn.Handshake(); err != nil {
log.Printf("error from TLS handshake: %s", err)
break
}
- _, err = c.Write([]byte("hello, world\n"))
+ _, err = conn.Write([]byte("hello, world\n"))
if err != nil {
- log.Printf("error from TLS: %s", err)
+ log.Printf("error from Write: %s", err)
continue
}
- st := c.(*Conn).ConnectionState()
- if len(st.PeerCertificates) > 0 {
- log.Print("Handling request from client ", st.PeerCertificates[0].Subject.CommonName)
- } else {
- log.Print("Handling request from anon client")
- }
+ conn.Close()
- c.Close()
+ record.WriteTo(os.Stdout)
}
}
@@ -296,30 +433,23 @@ func loadPEMCert(in string) *x509.Certificate {
// Script of interaction with gnutls implementation.
// The values for this test are obtained by building and running in server mode:
-// % go test -run "TestRunServer" -serve
-// and then:
-// % gnutls-cli --insecure --debug 100 -p 10443 localhost > /tmp/log 2>&1
-// % python parse-gnutls-cli-debug-log.py < /tmp/log
+// % go test -test.run "TestRunServer" -serve
+// The recorded bytes are written to stdout.
var rc4ServerScript = [][]byte{
{
- 0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
- 0x76, 0x03, 0x02, 0x4e, 0xdd, 0xe6, 0xa5, 0xf7,
- 0x00, 0x36, 0xf7, 0x83, 0xec, 0x93, 0x7c, 0xd2,
- 0x4d, 0xe7, 0x7b, 0xf5, 0x4c, 0xf7, 0xe3, 0x86,
- 0xe8, 0xec, 0x3b, 0xbd, 0x2c, 0x9a, 0x3f, 0x57,
- 0xf0, 0xa4, 0xd4, 0x00, 0x00, 0x34, 0x00, 0x33,
- 0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
- 0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
- 0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
- 0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
- 0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
- 0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
- 0x00, 0x8a, 0x01, 0x00, 0x00, 0x19, 0x00, 0x09,
- 0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
- 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
+ 0x16, 0x03, 0x01, 0x00, 0x54, 0x01, 0x00, 0x00,
+ 0x50, 0x03, 0x01, 0x50, 0x77, 0x3d, 0xbd, 0x32,
+ 0x13, 0xd7, 0xea, 0x33, 0x65, 0x02, 0xb8, 0x70,
+ 0xb7, 0x84, 0xc4, 0x05, 0x1f, 0xa4, 0x24, 0xc4,
+ 0x91, 0x69, 0x04, 0x32, 0x96, 0xfe, 0x5b, 0x49,
+ 0x71, 0x60, 0x9a, 0x00, 0x00, 0x28, 0x00, 0x39,
+ 0x00, 0x38, 0x00, 0x35, 0x00, 0x16, 0x00, 0x13,
+ 0x00, 0x0a, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2f,
+ 0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12,
+ 0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08,
+ 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x02, 0x01,
+ 0x00,
},
-
{
0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -418,86 +548,145 @@ var rc4ServerScript = [][]byte{
0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x04, 0x0e,
0x00, 0x00, 0x00,
},
-
{
0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
- 0x82, 0x00, 0x80, 0x39, 0xe2, 0x0f, 0x49, 0xa0,
- 0xe6, 0xe4, 0x3b, 0x0c, 0x5f, 0xce, 0x39, 0x97,
- 0x6c, 0xb6, 0x41, 0xd9, 0xe1, 0x52, 0x8f, 0x43,
- 0xb3, 0xc6, 0x4f, 0x9a, 0xe2, 0x1e, 0xb9, 0x3b,
- 0xe3, 0x72, 0x17, 0x68, 0xb2, 0x0d, 0x7b, 0x71,
- 0x33, 0x96, 0x5c, 0xf9, 0xfe, 0x18, 0x8f, 0x2f,
- 0x2b, 0x82, 0xec, 0x03, 0xf2, 0x16, 0xa8, 0xf8,
- 0x39, 0xf9, 0xbb, 0x5a, 0xd3, 0x0c, 0xc1, 0x2a,
- 0x52, 0xa1, 0x90, 0x20, 0x6b, 0x24, 0xc9, 0x55,
- 0xee, 0x05, 0xd8, 0xb3, 0x43, 0x58, 0xf6, 0x7f,
- 0x68, 0x2d, 0xb3, 0xd1, 0x1b, 0x30, 0xaa, 0xdf,
- 0xfc, 0x85, 0xf1, 0xab, 0x14, 0x51, 0x91, 0x78,
- 0x29, 0x35, 0x65, 0xe0, 0x9c, 0xf6, 0xb7, 0x35,
- 0x33, 0xdb, 0x28, 0x93, 0x4d, 0x86, 0xbc, 0xfe,
- 0xaa, 0xd1, 0xc0, 0x2e, 0x4d, 0xec, 0xa2, 0x98,
- 0xca, 0x08, 0xb2, 0x91, 0x14, 0xde, 0x97, 0x3a,
- 0xc4, 0x6b, 0x49, 0x14, 0x03, 0x01, 0x00, 0x01,
- 0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0x7a, 0xcb,
- 0x3b, 0x0e, 0xbb, 0x7a, 0x56, 0x39, 0xaf, 0x83,
- 0xae, 0xfd, 0x25, 0xfd, 0x64, 0xb4, 0x0c, 0x0c,
- 0x17, 0x46, 0x54, 0x2c, 0x6a, 0x07, 0x83, 0xc6,
- 0x46, 0x08, 0x0b, 0xcd, 0x15, 0x53, 0xef, 0x40,
- 0x4e, 0x56,
+ 0x82, 0x00, 0x80, 0x2d, 0x09, 0x7c, 0x7f, 0xfc,
+ 0x84, 0xce, 0xb3, 0x30, 0x9b, 0xf9, 0xb7, 0xc8,
+ 0xc3, 0xff, 0xee, 0x6f, 0x20, 0x8a, 0xf4, 0xfb,
+ 0x86, 0x55, 0x1f, 0x6a, 0xb4, 0x81, 0x50, 0x3a,
+ 0x46, 0x1b, 0xd3, 0xca, 0x4b, 0x11, 0xff, 0xef,
+ 0x02, 0xbc, 0x18, 0xb8, 0x4a, 0x7d, 0x43, 0x23,
+ 0x96, 0x92, 0x27, 0x7c, 0xca, 0xcf, 0xe6, 0x91,
+ 0xe8, 0x14, 0x97, 0x68, 0xb4, 0xe5, 0xc0, 0xc9,
+ 0x23, 0xdd, 0x54, 0x07, 0xa6, 0x2e, 0x8c, 0x98,
+ 0xfc, 0xc6, 0x8c, 0x04, 0x6b, 0x1b, 0x5f, 0xd5,
+ 0x3d, 0x8b, 0x6c, 0x55, 0x4f, 0x7a, 0xe6, 0x6c,
+ 0x74, 0x2c, 0x1e, 0x34, 0xdb, 0xfb, 0x00, 0xb1,
+ 0x4e, 0x10, 0x21, 0x16, 0xe0, 0x3e, 0xc5, 0x64,
+ 0x84, 0x28, 0x2b, 0x2b, 0x29, 0x47, 0x51, 0x34,
+ 0x76, 0x15, 0x20, 0x71, 0x0b, 0x30, 0xa1, 0x85,
+ 0xd5, 0x15, 0x18, 0x14, 0x64, 0x4b, 0x40, 0x7c,
+ 0x4f, 0xb3, 0x7b, 0x14, 0x03, 0x01, 0x00, 0x01,
+ 0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xab, 0xee,
+ 0xf5, 0x97, 0x5f, 0xc6, 0x78, 0xf3, 0xc6, 0x83,
+ 0x5b, 0x55, 0x4f, 0xcb, 0x45, 0x3f, 0xfa, 0xf7,
+ 0x05, 0x02, 0xc2, 0x63, 0x87, 0x18, 0xb5, 0x9a,
+ 0x62, 0xe2, 0x3f, 0x88, 0x5a, 0x60, 0x61, 0x72,
+ 0xfa, 0x9c,
},
-
{
0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
- 0x01, 0x00, 0x24, 0xd3, 0x72, 0xeb, 0x29, 0xb9,
- 0x15, 0x29, 0xb5, 0xe5, 0xb7, 0xef, 0x5c, 0xb2,
- 0x9d, 0xf6, 0xc8, 0x47, 0xd6, 0xa0, 0x84, 0xf0,
- 0x8c, 0xcb, 0xe6, 0xbe, 0xbc, 0xfb, 0x38, 0x90,
- 0x89, 0x60, 0xa2, 0xe8, 0xaa, 0xb3, 0x12, 0x17,
- 0x03, 0x01, 0x00, 0x21, 0x67, 0x4a, 0x3d, 0x31,
- 0x6c, 0x5a, 0x1c, 0xf9, 0x6e, 0xf1, 0xd8, 0x12,
- 0x0e, 0xb9, 0xfd, 0xfc, 0x66, 0x91, 0xd1, 0x1d,
- 0x6e, 0xe4, 0x55, 0xdd, 0x11, 0xb9, 0xb8, 0xa2,
- 0x65, 0xa1, 0x95, 0x64, 0x1c, 0x15, 0x03, 0x01,
- 0x00, 0x16, 0x9b, 0xa0, 0x24, 0xe3, 0xcb, 0xae,
- 0xad, 0x51, 0xb3, 0x63, 0x59, 0x78, 0x49, 0x24,
- 0x06, 0x6e, 0xee, 0x7a, 0xd7, 0x74, 0x53, 0x04,
+ 0x01, 0x00, 0x24, 0x72, 0xa4, 0xe4, 0xaa, 0xd2,
+ 0xc4, 0x39, 0x7e, 0x2a, 0xc1, 0x6f, 0x34, 0x42,
+ 0x28, 0xcb, 0x9d, 0x7a, 0x09, 0xca, 0x96, 0xad,
+ 0x0e, 0x11, 0x51, 0x8a, 0x06, 0xb0, 0xe9, 0xca,
+ 0xeb, 0xce, 0xe2, 0xd5, 0x2e, 0xc1, 0x8d, 0x17,
+ 0x03, 0x01, 0x00, 0x21, 0x2e, 0x61, 0x86, 0x17,
+ 0xdb, 0xa6, 0x30, 0xe2, 0x62, 0x06, 0x2a, 0x8b,
+ 0x75, 0x2c, 0x2d, 0xcf, 0xf5, 0x01, 0x11, 0x52,
+ 0x81, 0x38, 0xcf, 0xd5, 0xf7, 0xdc, 0x52, 0x31,
+ 0x1f, 0x97, 0x43, 0xc2, 0x71, 0x15, 0x03, 0x01,
+ 0x00, 0x16, 0xe0, 0x21, 0xfe, 0x36, 0x2e, 0x68,
+ 0x2c, 0xf1, 0xbe, 0x04, 0xec, 0xd4, 0xc6, 0xdd,
+ 0xac, 0x6f, 0x4c, 0x85, 0x32, 0x3f, 0x87, 0x1b,
},
}
var des3ServerScript = [][]byte{
{
- 0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
- 0x76, 0x03, 0x02, 0x4e, 0x84, 0xf4, 0x3c, 0xe4,
- 0xb8, 0xc7, 0xa0, 0x30, 0x55, 0x2a, 0xbc, 0xb7,
- 0x04, 0x6b, 0x6f, 0x87, 0x93, 0x96, 0xbd, 0x1a,
- 0x7a, 0x1e, 0xce, 0xd2, 0x0d, 0xf3, 0x01, 0x03,
- 0xbe, 0x7b, 0x17, 0x00, 0x00, 0x34, 0x00, 0x33,
- 0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
- 0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
- 0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
- 0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
- 0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
- 0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
- 0x00, 0x8a, 0x01, 0x00, 0x00, 0x19, 0x00, 0x09,
- 0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
- 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
+ 0x16, 0x03, 0x00, 0x00, 0xc5, 0x01, 0x00, 0x00,
+ 0xc1, 0x03, 0x03, 0x50, 0xae, 0x5d, 0x38, 0xec,
+ 0xaa, 0x2f, 0x41, 0xf9, 0xd2, 0x7b, 0xa1, 0xfd,
+ 0x0f, 0xff, 0x4e, 0x54, 0x0e, 0x15, 0x57, 0xaf,
+ 0x2c, 0x91, 0xb5, 0x35, 0x5b, 0x2e, 0xb0, 0xec,
+ 0x20, 0xe5, 0xd2, 0x00, 0x00, 0x50, 0xc0, 0x09,
+ 0xc0, 0x23, 0xc0, 0x2b, 0xc0, 0x0a, 0xc0, 0x24,
+ 0xc0, 0x2c, 0xc0, 0x08, 0xc0, 0x13, 0xc0, 0x27,
+ 0xc0, 0x2f, 0xc0, 0x14, 0xc0, 0x30, 0xc0, 0x12,
+ 0x00, 0x33, 0x00, 0x67, 0x00, 0x45, 0x00, 0x9e,
+ 0x00, 0x39, 0x00, 0x6b, 0x00, 0x88, 0x00, 0x16,
+ 0x00, 0x32, 0x00, 0x40, 0x00, 0x44, 0x00, 0xa2,
+ 0x00, 0x38, 0x00, 0x6a, 0x00, 0x87, 0x00, 0x13,
+ 0x00, 0x66, 0x00, 0x2f, 0x00, 0x3c, 0x00, 0x41,
+ 0x00, 0x9c, 0x00, 0x35, 0x00, 0x3d, 0x00, 0x84,
+ 0x00, 0x0a, 0x00, 0x05, 0x00, 0x04, 0x01, 0x00,
+ 0x00, 0x48, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x01, 0x00,
+ 0x00, 0x23, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c,
+ 0x00, 0x0a, 0x00, 0x13, 0x00, 0x15, 0x00, 0x17,
+ 0x00, 0x18, 0x00, 0x19, 0x00, 0x0b, 0x00, 0x02,
+ 0x01, 0x00, 0x00, 0x0d, 0x00, 0x1c, 0x00, 0x1a,
+ 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x05, 0x01,
+ 0x05, 0x03, 0x06, 0x01, 0x06, 0x03, 0x03, 0x01,
+ 0x03, 0x02, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02,
+ 0x02, 0x03,
},
-
{
- 0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
- 0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x16, 0x03, 0x01, 0x00, 0x30, 0x02, 0x00, 0x00,
+ 0x2c, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x16,
- 0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
- 0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
- 0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
- 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
- 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
- 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00,
+ 0x04, 0x00, 0x23, 0x00, 0x00, 0x16, 0x03, 0x01,
+ 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba, 0x00, 0x02,
+ 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82, 0x02, 0xb0,
+ 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03, 0x02, 0x01,
+ 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0, 0xbb, 0xa4,
+ 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x05, 0x05, 0x00, 0x30, 0x45, 0x31, 0x0b, 0x30,
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
+ 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d,
+ 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
+ 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
+ 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69,
+ 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c,
+ 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30,
+ 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39,
+ 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30,
+ 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, 0x33,
+ 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41,
+ 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
+ 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65,
+ 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21,
+ 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+ 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
+ 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74,
+ 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74,
+ 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30,
+ 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0x79,
+ 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf, 0x46, 0x10,
+ 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b, 0x07, 0x43,
+ 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a, 0x43, 0x85,
+ 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65, 0x4c, 0x2c,
+ 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4, 0x82, 0xe5,
+ 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62, 0xa5, 0x2c,
+ 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c, 0x7a, 0x56,
+ 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58, 0x7b, 0x26,
+ 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0, 0xc9, 0x21,
+ 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f, 0x5a, 0xbf,
+ 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18, 0x99, 0x07,
+ 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1, 0x04, 0x39,
+ 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9, 0x7c, 0xe3,
+ 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01, 0xcf, 0xaf,
+ 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d, 0xdb, 0xdb,
+ 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79, 0x02, 0x03,
+ 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81,
+ 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad, 0xe2, 0x85,
+ 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, 0x23,
+ 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, 0x39,
+ 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04,
+ 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1, 0xad, 0xe2,
+ 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce,
+ 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88,
+ 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31,
0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
@@ -506,172 +695,207 @@ var des3ServerScript = [][]byte{
0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
- 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
- 0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
- 0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
- 0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
- 0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
- 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
- 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
- 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
- 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
- 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
- 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
- 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
- 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
- 0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
- 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
- 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
- 0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
- 0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
- 0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
- 0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
- 0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
- 0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
- 0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
- 0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
- 0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
- 0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
- 0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
- 0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
- 0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
- 0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
- 0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
- 0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
- 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
- 0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
- 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
- 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
- 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
- 0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
- 0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
- 0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
- 0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
- 0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
- 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
- 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
- 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
- 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
- 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
- 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
- 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
- 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
- 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
- 0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
- 0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
- 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
- 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
- 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
- 0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
- 0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
- 0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
- 0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
- 0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
- 0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
- 0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
- 0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
- 0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
- 0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
- 0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
- 0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
- 0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
- 0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
- 0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
- 0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
- 0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x04, 0x0e,
- 0x00, 0x00, 0x00,
+ 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0x85,
+ 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30,
+ 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05,
+ 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00,
+ 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b, 0xb1, 0x59,
+ 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0, 0x14, 0xd7,
+ 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5, 0x5a, 0x95,
+ 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae, 0x12, 0x66,
+ 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e, 0x60, 0xd3,
+ 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5, 0x25, 0x13,
+ 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30, 0x1d, 0xba,
+ 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7, 0xd7, 0x31,
+ 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78, 0xea, 0x50,
+ 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d, 0x5a, 0x5f,
+ 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75, 0x90, 0x96,
+ 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd, 0x98, 0x1f,
+ 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c, 0xa3, 0x1b,
+ 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57, 0xe9, 0x70,
+ 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b, 0x26, 0x6e,
+ 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7, 0xbd, 0xd9,
+ 0x16, 0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00,
+ 0x00,
},
-
{
0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
- 0x82, 0x00, 0x80, 0xae, 0xcf, 0x4f, 0x70, 0x0e,
- 0xe5, 0xe7, 0xba, 0xef, 0x0c, 0x66, 0xe9, 0xae,
- 0x76, 0xf4, 0xe0, 0xbc, 0x1c, 0x22, 0x5b, 0x72,
- 0xc9, 0x68, 0x63, 0x44, 0xec, 0x72, 0xc2, 0xca,
- 0xac, 0xc2, 0xf5, 0x5c, 0x28, 0xa1, 0xaf, 0xd0,
- 0xc2, 0xf7, 0x79, 0x71, 0x32, 0x73, 0x86, 0xea,
- 0x39, 0xf6, 0x04, 0x26, 0x19, 0x84, 0x1d, 0x7d,
- 0xa1, 0x21, 0xa6, 0x88, 0xbf, 0x33, 0x5a, 0x64,
- 0xb0, 0xc2, 0xcc, 0x19, 0x7a, 0x8b, 0x6e, 0x94,
- 0x9e, 0x2e, 0x20, 0xbe, 0xdc, 0xe9, 0x8e, 0xae,
- 0x5c, 0x39, 0xc8, 0xcd, 0x0e, 0x19, 0x9a, 0xa2,
- 0xfc, 0x3f, 0x61, 0x9a, 0xca, 0x58, 0x69, 0x0d,
- 0xa8, 0x7b, 0xbe, 0x98, 0x8f, 0xb9, 0x9d, 0x8b,
- 0x68, 0x65, 0xa9, 0x74, 0xcc, 0x8d, 0x0c, 0xb2,
- 0xc4, 0x0f, 0xdc, 0x56, 0x3e, 0x44, 0x61, 0x0a,
- 0x26, 0x93, 0x99, 0xef, 0x67, 0xff, 0x6e, 0x73,
- 0x01, 0xa1, 0x90, 0x14, 0x03, 0x01, 0x00, 0x01,
- 0x01, 0x16, 0x03, 0x01, 0x00, 0x60, 0x49, 0x36,
- 0xc8, 0x38, 0x95, 0xe4, 0x5d, 0x8e, 0x80, 0x10,
- 0x26, 0x9f, 0x87, 0x7d, 0xcd, 0xb9, 0x32, 0x6c,
- 0xff, 0xaa, 0xe0, 0x07, 0xec, 0x33, 0xe2, 0x36,
- 0x9d, 0xd5, 0x83, 0x2c, 0xf0, 0x0a, 0xa0, 0xa8,
- 0x12, 0x9f, 0xca, 0x72, 0xda, 0x70, 0x7d, 0x76,
- 0x80, 0x12, 0x88, 0x07, 0xaa, 0x27, 0x62, 0x33,
- 0xab, 0x55, 0xad, 0x3c, 0x2b, 0x54, 0xc4, 0x1c,
- 0x91, 0xfd, 0x8f, 0x9c, 0xa7, 0x8b, 0x75, 0x10,
- 0xa8, 0x6e, 0xfc, 0x30, 0x52, 0x8a, 0x61, 0x02,
- 0xdb, 0x9c, 0x6f, 0xc8, 0x19, 0x93, 0x5d, 0x41,
- 0x1d, 0x36, 0x68, 0x0b, 0xec, 0x30, 0xae, 0xfb,
- 0x90, 0xdb, 0x6d, 0x83, 0xb0, 0xf2,
+ 0x82, 0x00, 0x80, 0x51, 0x04, 0xf1, 0x7a, 0xbf,
+ 0xe8, 0xa5, 0x86, 0x09, 0xa7, 0xf3, 0xcc, 0x93,
+ 0x00, 0x10, 0x5b, 0xb8, 0xc1, 0x51, 0x0d, 0x5b,
+ 0xcd, 0xed, 0x26, 0x01, 0x69, 0x73, 0xf4, 0x05,
+ 0x8a, 0x6a, 0xc3, 0xb1, 0x9e, 0x84, 0x4e, 0x39,
+ 0xcf, 0x5e, 0x55, 0xa9, 0x70, 0x19, 0x96, 0x91,
+ 0xcd, 0x2c, 0x78, 0x3c, 0xa2, 0x6d, 0xb0, 0x49,
+ 0x86, 0xf6, 0xd1, 0x3a, 0xde, 0x00, 0x4b, 0xa6,
+ 0x25, 0xbf, 0x85, 0x39, 0xce, 0xb1, 0xcf, 0xbc,
+ 0x16, 0xc7, 0x66, 0xac, 0xf8, 0xd2, 0x3b, 0xd1,
+ 0xcc, 0x16, 0xac, 0x63, 0x3c, 0xbe, 0xd9, 0xb6,
+ 0x6a, 0xe4, 0x13, 0x8a, 0xf4, 0x56, 0x2f, 0x92,
+ 0x54, 0xd8, 0xf0, 0x84, 0x01, 0x32, 0x1a, 0xa9,
+ 0x2d, 0xaf, 0x82, 0x0e, 0x00, 0xfa, 0x07, 0x88,
+ 0xd9, 0x87, 0xe7, 0xdc, 0x9e, 0xe9, 0x72, 0x49,
+ 0xb8, 0xfa, 0x8c, 0x7b, 0x07, 0x0b, 0x03, 0x7c,
+ 0x10, 0x8c, 0x8a, 0x14, 0x03, 0x01, 0x00, 0x01,
+ 0x01, 0x16, 0x03, 0x01, 0x00, 0xa8, 0x61, 0xa4,
+ 0xf4, 0x5f, 0x8a, 0x1f, 0x5c, 0x92, 0x3f, 0x8c,
+ 0xdb, 0xd6, 0x10, 0xcd, 0x9e, 0xe7, 0xf0, 0xc4,
+ 0x3c, 0xb6, 0x1c, 0x9a, 0x56, 0x73, 0x7f, 0xa6,
+ 0x14, 0x24, 0xcb, 0x96, 0x1f, 0xe0, 0xaf, 0xcd,
+ 0x3c, 0x66, 0x43, 0xb7, 0x37, 0x65, 0x34, 0x47,
+ 0xf8, 0x43, 0xf1, 0xcc, 0x15, 0xb8, 0xdc, 0x35,
+ 0xe0, 0xa4, 0x2d, 0x78, 0x94, 0xe0, 0x02, 0xf3,
+ 0x76, 0x46, 0xf7, 0x9b, 0x8d, 0x0d, 0x5d, 0x0b,
+ 0xd3, 0xdd, 0x9a, 0x9e, 0x62, 0x2e, 0xc5, 0x98,
+ 0x75, 0x63, 0x0c, 0xbf, 0x8e, 0x49, 0x33, 0x23,
+ 0x7c, 0x00, 0xcf, 0xfb, 0xcf, 0xba, 0x0f, 0x41,
+ 0x39, 0x89, 0xb9, 0xcc, 0x59, 0xd0, 0x2b, 0xb6,
+ 0xec, 0x04, 0xe2, 0xc0, 0x52, 0xc7, 0xcf, 0x71,
+ 0x47, 0xff, 0x70, 0x7e, 0xa9, 0xbd, 0x1c, 0xdd,
+ 0x17, 0xa5, 0x6c, 0xb7, 0x10, 0x4f, 0x42, 0x18,
+ 0x37, 0x69, 0xa9, 0xd2, 0xb3, 0x18, 0x84, 0x92,
+ 0xa7, 0x47, 0x21, 0xf6, 0x95, 0x63, 0x29, 0xd6,
+ 0xa5, 0xb6, 0xda, 0x65, 0x67, 0x69, 0xc4, 0x26,
+ 0xac, 0x8b, 0x08, 0x58, 0xdd, 0x3c, 0x31, 0x20,
+ 0xd5, 0x0c, 0x88, 0x72, 0x18, 0x16, 0x88, 0x1e,
+ 0x4a, 0x0f, 0xe1, 0xcf, 0x95, 0x24,
},
-
{
- 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
- 0x01, 0x00, 0x28, 0x07, 0xf3, 0x33, 0x84, 0xb1,
- 0x5d, 0x2b, 0x52, 0xa4, 0x63, 0x3c, 0x32, 0xe0,
- 0x0d, 0x22, 0xf5, 0x23, 0xec, 0xf9, 0xa6, 0xec,
- 0xc0, 0x12, 0x69, 0x88, 0xf6, 0x7d, 0x37, 0xcd,
- 0xc2, 0x74, 0x2f, 0xef, 0xf6, 0x49, 0x15, 0xea,
- 0x88, 0x3f, 0x55, 0x17, 0x03, 0x01, 0x00, 0x28,
- 0xaf, 0x00, 0x84, 0xff, 0x11, 0x01, 0x6d, 0xba,
- 0x39, 0x5e, 0x45, 0xe1, 0x52, 0x5e, 0xc1, 0xab,
- 0xde, 0x5b, 0x16, 0xdd, 0xd6, 0x61, 0x57, 0xb8,
- 0x66, 0x8b, 0x2d, 0xde, 0x51, 0x41, 0xc5, 0x09,
- 0xb3, 0x6a, 0x06, 0x43, 0xb4, 0x73, 0x5c, 0xf1,
- 0x15, 0x03, 0x01, 0x00, 0x18, 0xbd, 0x65, 0xb2,
- 0xce, 0x77, 0x2e, 0xf9, 0x11, 0xc4, 0x80, 0x43,
- 0x5a, 0x73, 0x8b, 0x73, 0xdd, 0xf0, 0x54, 0x44,
- 0x7c, 0x56, 0x19, 0x54, 0xda,
+ 0x16, 0x03, 0x01, 0x00, 0x72, 0x04, 0x00, 0x00,
+ 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65,
+ 0xe8, 0x4b, 0xde, 0xef, 0xba, 0x3e, 0x18, 0x1c,
+ 0x1e, 0x5e, 0xbc, 0x87, 0xf1, 0x87, 0x8d, 0x72,
+ 0xe3, 0xbe, 0x0f, 0xdf, 0xfd, 0xd0, 0xb2, 0x89,
+ 0xf8, 0x05, 0x9a, 0x52, 0x47, 0x77, 0x9e, 0xe8,
+ 0xb1, 0x1d, 0x18, 0xed, 0x6a, 0x4b, 0x63, 0x1d,
+ 0xf1, 0x62, 0xd2, 0x65, 0x21, 0x26, 0x73, 0xd4,
+ 0x35, 0x5b, 0x95, 0x89, 0x12, 0x59, 0x23, 0x8c,
+ 0xc3, 0xfc, 0xf9, 0x4d, 0x21, 0x79, 0xa0, 0xbd,
+ 0xff, 0x33, 0xa2, 0x3d, 0x0b, 0x6f, 0x89, 0xc9,
+ 0x23, 0xe4, 0xe7, 0x9f, 0x1d, 0x98, 0xf6, 0xed,
+ 0x02, 0x8d, 0xac, 0x1a, 0xf9, 0xcb, 0xa5, 0x14,
+ 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01,
+ 0x00, 0x28, 0x91, 0x56, 0x80, 0xe2, 0x6d, 0x51,
+ 0x88, 0x03, 0xf8, 0x49, 0xe6, 0x6a, 0x5a, 0xfb,
+ 0x2f, 0x0b, 0xb5, 0xa1, 0x0d, 0x63, 0x83, 0xae,
+ 0xb9, 0xbc, 0x05, 0xf0, 0x81, 0x00, 0x61, 0x83,
+ 0x38, 0xda, 0x14, 0xf6, 0xea, 0xd8, 0x78, 0x65,
+ 0xc7, 0x26, 0x17, 0x03, 0x01, 0x00, 0x18, 0x81,
+ 0x30, 0x8b, 0x22, 0x5a, 0xd3, 0x7f, 0xc8, 0xf2,
+ 0x8a, 0x6b, 0xa3, 0xba, 0x4d, 0xe7, 0x6e, 0xd2,
+ 0xfd, 0xbf, 0xf2, 0xc5, 0x28, 0xa0, 0x62, 0x17,
+ 0x03, 0x01, 0x00, 0x28, 0x17, 0x83, 0x3c, 0x78,
+ 0x18, 0xfa, 0x8d, 0x58, 0x5c, 0xaa, 0x05, 0x7d,
+ 0x67, 0x96, 0x11, 0x60, 0x11, 0xc0, 0x1e, 0x0d,
+ 0x6a, 0x6e, 0x5f, 0x1d, 0x98, 0x4b, 0xff, 0x82,
+ 0xee, 0x21, 0x06, 0x29, 0xd3, 0x8b, 0x80, 0x78,
+ 0x39, 0x05, 0x34, 0x9b, 0x15, 0x03, 0x01, 0x00,
+ 0x18, 0xa9, 0x38, 0x18, 0x4f, 0x9d, 0x84, 0x75,
+ 0x88, 0x53, 0xd6, 0x85, 0xc2, 0x15, 0x4b, 0xe3,
+ 0xe3, 0x35, 0x9a, 0x74, 0xc9, 0x3e, 0x13, 0xc1,
+ 0x8c,
},
}
var aesServerScript = [][]byte{
{
- 0x16, 0x03, 0x02, 0x00, 0x7f, 0x01, 0x00, 0x00,
- 0x7b, 0x03, 0x02, 0x4d, 0x08, 0x2d, 0x0b, 0xb3,
- 0x57, 0x85, 0x71, 0x4b, 0xfb, 0x34, 0xab, 0x16,
- 0xd4, 0x92, 0x50, 0x81, 0x16, 0x95, 0x11, 0x28,
- 0x1a, 0xcb, 0xff, 0x09, 0x4d, 0x23, 0xa6, 0xfe,
- 0x2e, 0xbb, 0x78, 0x00, 0x00, 0x34, 0x00, 0x33,
- 0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
- 0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
- 0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
- 0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
- 0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
- 0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
- 0x00, 0x8a, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x09,
- 0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
- 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0xff,
- 0x01, 0x00, 0x01, 0x00,
+ 0x16, 0x03, 0x00, 0x00, 0xc5, 0x01, 0x00, 0x00,
+ 0xc1, 0x03, 0x03, 0x50, 0xae, 0x5c, 0xe9, 0x5e,
+ 0x31, 0x93, 0x82, 0xa5, 0x6f, 0x51, 0x82, 0xc8,
+ 0x55, 0x4f, 0x1f, 0x2e, 0x90, 0x98, 0x81, 0x13,
+ 0x27, 0x80, 0x68, 0xb4, 0x2d, 0xba, 0x3a, 0x76,
+ 0xd8, 0xd7, 0x2c, 0x00, 0x00, 0x50, 0xc0, 0x09,
+ 0xc0, 0x23, 0xc0, 0x2b, 0xc0, 0x0a, 0xc0, 0x24,
+ 0xc0, 0x2c, 0xc0, 0x08, 0xc0, 0x13, 0xc0, 0x27,
+ 0xc0, 0x2f, 0xc0, 0x14, 0xc0, 0x30, 0xc0, 0x12,
+ 0x00, 0x33, 0x00, 0x67, 0x00, 0x45, 0x00, 0x9e,
+ 0x00, 0x39, 0x00, 0x6b, 0x00, 0x88, 0x00, 0x16,
+ 0x00, 0x32, 0x00, 0x40, 0x00, 0x44, 0x00, 0xa2,
+ 0x00, 0x38, 0x00, 0x6a, 0x00, 0x87, 0x00, 0x13,
+ 0x00, 0x66, 0x00, 0x2f, 0x00, 0x3c, 0x00, 0x41,
+ 0x00, 0x9c, 0x00, 0x35, 0x00, 0x3d, 0x00, 0x84,
+ 0x00, 0x0a, 0x00, 0x05, 0x00, 0x04, 0x01, 0x00,
+ 0x00, 0x48, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x01, 0x00,
+ 0x00, 0x23, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c,
+ 0x00, 0x0a, 0x00, 0x13, 0x00, 0x15, 0x00, 0x17,
+ 0x00, 0x18, 0x00, 0x19, 0x00, 0x0b, 0x00, 0x02,
+ 0x01, 0x00, 0x00, 0x0d, 0x00, 0x1c, 0x00, 0x1a,
+ 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x05, 0x01,
+ 0x05, 0x03, 0x06, 0x01, 0x06, 0x03, 0x03, 0x01,
+ 0x03, 0x02, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02,
+ 0x02, 0x03,
},
-
{
- 0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
- 0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x16, 0x03, 0x01, 0x00, 0x30, 0x02, 0x00, 0x00,
+ 0x2c, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x16,
- 0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
- 0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
- 0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
- 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
- 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
- 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00,
+ 0x04, 0x00, 0x23, 0x00, 0x00, 0x16, 0x03, 0x01,
+ 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba, 0x00, 0x02,
+ 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82, 0x02, 0xb0,
+ 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03, 0x02, 0x01,
+ 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0, 0xbb, 0xa4,
+ 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x05, 0x05, 0x00, 0x30, 0x45, 0x31, 0x0b, 0x30,
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
+ 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d,
+ 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
+ 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
+ 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69,
+ 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c,
+ 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30,
+ 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39,
+ 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30,
+ 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, 0x33,
+ 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41,
+ 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
+ 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65,
+ 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21,
+ 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+ 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
+ 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74,
+ 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74,
+ 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30,
+ 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0x79,
+ 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf, 0x46, 0x10,
+ 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b, 0x07, 0x43,
+ 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a, 0x43, 0x85,
+ 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65, 0x4c, 0x2c,
+ 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4, 0x82, 0xe5,
+ 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62, 0xa5, 0x2c,
+ 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c, 0x7a, 0x56,
+ 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58, 0x7b, 0x26,
+ 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0, 0xc9, 0x21,
+ 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f, 0x5a, 0xbf,
+ 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18, 0x99, 0x07,
+ 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1, 0x04, 0x39,
+ 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9, 0x7c, 0xe3,
+ 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01, 0xcf, 0xaf,
+ 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d, 0xdb, 0xdb,
+ 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79, 0x02, 0x03,
+ 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81,
+ 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad, 0xe2, 0x85,
+ 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, 0x23,
+ 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, 0x39,
+ 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04,
+ 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1, 0xad, 0xe2,
+ 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce,
+ 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88,
+ 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31,
0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
@@ -680,136 +904,144 @@ var aesServerScript = [][]byte{
0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
- 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
- 0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
- 0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
- 0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
- 0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
- 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
- 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
- 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
- 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
- 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
- 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
- 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
- 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
- 0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
- 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
- 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
- 0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
- 0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
- 0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
- 0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
- 0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
- 0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
- 0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
- 0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
- 0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
- 0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
- 0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
- 0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
- 0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
- 0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
- 0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
- 0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
- 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
- 0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
- 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
- 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
- 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
- 0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
- 0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
- 0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
- 0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
- 0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
- 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
- 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
- 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
- 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
- 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
- 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
- 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
- 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
- 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
- 0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
- 0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
- 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
- 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
- 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
- 0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
- 0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
- 0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
- 0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
- 0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
- 0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
- 0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
- 0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
- 0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
- 0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
- 0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
- 0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
- 0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
- 0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
- 0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
- 0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
- 0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x04, 0x0e,
- 0x00, 0x00, 0x00,
+ 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0x85,
+ 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30,
+ 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05,
+ 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00,
+ 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b, 0xb1, 0x59,
+ 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0, 0x14, 0xd7,
+ 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5, 0x5a, 0x95,
+ 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae, 0x12, 0x66,
+ 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e, 0x60, 0xd3,
+ 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5, 0x25, 0x13,
+ 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30, 0x1d, 0xba,
+ 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7, 0xd7, 0x31,
+ 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78, 0xea, 0x50,
+ 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d, 0x5a, 0x5f,
+ 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75, 0x90, 0x96,
+ 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd, 0x98, 0x1f,
+ 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c, 0xa3, 0x1b,
+ 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57, 0xe9, 0x70,
+ 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b, 0x26, 0x6e,
+ 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7, 0xbd, 0xd9,
+ 0x16, 0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00,
+ 0x00,
},
-
{
0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
- 0x82, 0x00, 0x80, 0x71, 0x9c, 0xe7, 0x23, 0xfc,
- 0xb9, 0x19, 0x29, 0x82, 0xbf, 0xef, 0x08, 0xf7,
- 0x99, 0x36, 0xc3, 0x4c, 0x6f, 0x05, 0xd2, 0x8b,
- 0x62, 0x2b, 0x19, 0x9b, 0x7f, 0xc0, 0xcc, 0x48,
- 0x30, 0x5f, 0xcd, 0xc3, 0x70, 0x55, 0x53, 0x73,
- 0xfa, 0x79, 0x74, 0xf3, 0xa3, 0x76, 0x9f, 0xa1,
- 0x7f, 0x98, 0xc2, 0xc0, 0xe3, 0xc5, 0xa0, 0x31,
- 0x2f, 0xa6, 0xe8, 0x1e, 0x61, 0x46, 0xb3, 0x9b,
- 0x4b, 0x16, 0xf1, 0x2d, 0xc7, 0x63, 0x7f, 0x79,
- 0x22, 0x30, 0xd1, 0xf2, 0xfc, 0x77, 0x98, 0x0a,
- 0x16, 0x11, 0x63, 0x71, 0x7f, 0x70, 0xef, 0x16,
- 0xbb, 0x39, 0x87, 0x34, 0xac, 0x49, 0xbd, 0x07,
- 0x67, 0xcb, 0x9c, 0xcc, 0xde, 0xef, 0xb1, 0xe0,
- 0xdb, 0x01, 0xb5, 0x35, 0xa9, 0xb3, 0x10, 0x0c,
- 0x4b, 0xee, 0xb3, 0x4e, 0xfd, 0xbe, 0x15, 0x27,
- 0xf0, 0x46, 0xb2, 0x38, 0xba, 0x5f, 0xcc, 0x89,
- 0xec, 0x29, 0x82, 0x14, 0x03, 0x01, 0x00, 0x01,
- 0x01, 0x16, 0x03, 0x01, 0x00, 0x30, 0x3c, 0xfb,
- 0xa4, 0x12, 0xcb, 0x00, 0xf9, 0x57, 0x7e, 0x9b,
- 0xc9, 0xdc, 0x0c, 0xba, 0x9a, 0x81, 0x62, 0xfb,
- 0x26, 0x13, 0x53, 0xfe, 0xaa, 0xcc, 0x82, 0xbb,
- 0xb6, 0x67, 0x7f, 0x39, 0xbe, 0x4d, 0xbb, 0xc0,
- 0x6c, 0x24, 0x31, 0x83, 0xa5, 0x50, 0x3a, 0x75,
- 0x32, 0x64, 0xb5, 0xdb, 0xbe, 0x0a,
+ 0x82, 0x00, 0x80, 0x51, 0x2e, 0xec, 0x0d, 0x86,
+ 0xf3, 0x9f, 0xf2, 0x77, 0x04, 0x27, 0x2b, 0x0e,
+ 0x9c, 0xab, 0x35, 0x84, 0x65, 0xff, 0x36, 0xef,
+ 0xc0, 0x08, 0xc9, 0x1d, 0x9f, 0x29, 0xae, 0x8d,
+ 0xc5, 0x66, 0x81, 0x31, 0x92, 0x5e, 0x3d, 0xac,
+ 0xaa, 0x37, 0x28, 0x2c, 0x06, 0x91, 0xa6, 0xc2,
+ 0xd0, 0x83, 0x34, 0x24, 0x1c, 0x88, 0xfc, 0x0a,
+ 0xcf, 0xbf, 0xc2, 0x94, 0xe2, 0xed, 0xa7, 0x6a,
+ 0xa8, 0x8d, 0x3d, 0xf7, 0x06, 0x7d, 0x69, 0xf8,
+ 0x0d, 0xb2, 0xf7, 0xe4, 0x45, 0xcb, 0x0a, 0x25,
+ 0xcb, 0xb2, 0x2e, 0x38, 0x9a, 0x84, 0x75, 0xe8,
+ 0xe1, 0x42, 0x39, 0xa2, 0x18, 0x0e, 0x48, 0xca,
+ 0x33, 0x16, 0x4e, 0xf6, 0x2f, 0xec, 0x07, 0xe7,
+ 0x57, 0xe1, 0x20, 0x40, 0x40, 0x6d, 0x4e, 0x29,
+ 0x04, 0x1a, 0x8c, 0x99, 0xfb, 0x19, 0x3c, 0xaa,
+ 0x75, 0x64, 0xd3, 0xa6, 0xe6, 0xed, 0x3f, 0x5a,
+ 0xd2, 0xc9, 0x80, 0x14, 0x03, 0x01, 0x00, 0x01,
+ 0x01, 0x16, 0x03, 0x01, 0x01, 0x10, 0xe9, 0x9e,
+ 0x06, 0x92, 0x18, 0xbf, 0x5e, 0xaf, 0x33, 0xc1,
+ 0xbf, 0x0e, 0x12, 0x07, 0x48, 0x4f, 0x6b, 0x6c,
+ 0xf5, 0x23, 0x5e, 0x87, 0xa7, 0xd3, 0x50, 0x79,
+ 0x38, 0xdc, 0xe0, 0x49, 0xd3, 0x81, 0x21, 0x12,
+ 0xd0, 0x3d, 0x9a, 0xfb, 0x83, 0xc1, 0x8b, 0xfc,
+ 0x14, 0xd5, 0xd5, 0xa7, 0xa3, 0x34, 0x14, 0x71,
+ 0xbe, 0xea, 0x37, 0x18, 0x12, 0x7f, 0x41, 0xfb,
+ 0xc5, 0x51, 0x17, 0x9d, 0x96, 0x58, 0x14, 0xfb,
+ 0x4f, 0xd7, 0xd3, 0x15, 0x0f, 0xec, 0x5a, 0x0d,
+ 0x35, 0xbb, 0x3c, 0x81, 0x5b, 0x3f, 0xdf, 0x52,
+ 0xa4, 0x4c, 0xcd, 0x13, 0xe1, 0x10, 0x37, 0x34,
+ 0xbf, 0xb4, 0x80, 0x1e, 0x8d, 0xe2, 0xc3, 0x7a,
+ 0x0f, 0x7b, 0x7d, 0x23, 0xeb, 0xd0, 0x99, 0x69,
+ 0xad, 0x0a, 0x2d, 0xb3, 0x6c, 0xd6, 0x80, 0x11,
+ 0x7f, 0x6c, 0xed, 0x1b, 0xcd, 0x08, 0x22, 0x56,
+ 0x90, 0x0e, 0xa4, 0xc3, 0x29, 0x33, 0x96, 0x30,
+ 0x34, 0x94, 0xa1, 0xeb, 0x9c, 0x1b, 0x5a, 0xd1,
+ 0x03, 0x61, 0xf9, 0xdd, 0xf3, 0x64, 0x8a, 0xfd,
+ 0x5f, 0x44, 0xdb, 0x2e, 0xa7, 0xfd, 0xe1, 0x1a,
+ 0x66, 0xc5, 0x01, 0x9c, 0xc7, 0xd1, 0xc4, 0xd3,
+ 0xea, 0x14, 0x3c, 0xed, 0x74, 0xbb, 0x1b, 0x97,
+ 0x8f, 0xf1, 0x29, 0x39, 0x33, 0x92, 0x93, 0x4e,
+ 0xf5, 0x87, 0x91, 0x61, 0x65, 0x8d, 0x27, 0x8d,
+ 0x76, 0xc1, 0xfa, 0x6a, 0x99, 0x80, 0xb1, 0x9b,
+ 0x29, 0x53, 0xce, 0x3e, 0xb6, 0x9a, 0xce, 0x3c,
+ 0x19, 0x5e, 0x48, 0x83, 0xaa, 0xa7, 0x66, 0x98,
+ 0x59, 0xf4, 0xbb, 0xf2, 0xbc, 0xd9, 0xc5, 0x9a,
+ 0xc8, 0x2c, 0x63, 0x58, 0xd5, 0xd4, 0xbc, 0x03,
+ 0xa9, 0x06, 0xa9, 0x80, 0x0d, 0xb3, 0x46, 0x2d,
+ 0xe3, 0xc6, 0xaf, 0x1a, 0x39, 0x18, 0x7e, 0x1e,
+ 0x83, 0x80, 0x46, 0x11, 0xd2, 0x13, 0x9f, 0xda,
+ 0xfc, 0x2d, 0x42, 0xaa, 0x5a, 0x1d, 0x4c, 0x31,
+ 0xe5, 0x58, 0x78, 0x5e, 0xe2, 0x04, 0xd6, 0x23,
+ 0x7f, 0x3f, 0x06, 0xc0, 0x54, 0xf8,
},
-
{
- 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
- 0x01, 0x00, 0x30, 0x43, 0x24, 0x42, 0x55, 0x08,
- 0xe4, 0xc2, 0x15, 0xc9, 0xdb, 0x71, 0x69, 0xee,
- 0x09, 0xc5, 0x1c, 0xfd, 0x46, 0x10, 0xa0, 0x68,
- 0x21, 0xf2, 0x48, 0xac, 0x6c, 0xc0, 0x2b, 0x62,
- 0x07, 0x8f, 0x48, 0x33, 0x0a, 0x6b, 0x62, 0x28,
- 0x2e, 0x2c, 0xad, 0xcb, 0x34, 0x85, 0xca, 0x2e,
- 0xcd, 0x84, 0xf0,
+ 0x16, 0x03, 0x01, 0x00, 0x72, 0x04, 0x00, 0x00,
+ 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65,
+ 0xe8, 0x4b, 0xfb, 0xef, 0xba, 0xed, 0xc5, 0x36,
+ 0xc8, 0x5a, 0x41, 0x3f, 0x05, 0xfa, 0xfe, 0x48,
+ 0xc3, 0x91, 0x12, 0x8b, 0xe8, 0x32, 0x6a, 0x9f,
+ 0xdc, 0x97, 0xe2, 0x77, 0xb9, 0x96, 0x2d, 0xd4,
+ 0xe5, 0xbd, 0xa1, 0xfd, 0x94, 0xbb, 0x74, 0x63,
+ 0xb1, 0x0c, 0x38, 0xbc, 0x6f, 0x69, 0xaf, 0xa3,
+ 0x46, 0x9c, 0x96, 0x41, 0xde, 0x59, 0x23, 0xff,
+ 0x15, 0x6b, 0x3a, 0xef, 0x91, 0x6d, 0x92, 0x44,
+ 0xdc, 0x72, 0x1f, 0x40, 0x3d, 0xb5, 0x34, 0x8f,
+ 0x2a, 0xac, 0x21, 0x69, 0x05, 0x6f, 0xb2, 0x60,
+ 0x32, 0x5d, 0x3d, 0x97, 0xb4, 0x24, 0x99, 0x14,
+ 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01,
+ 0x00, 0x30, 0x68, 0x27, 0x97, 0xca, 0x63, 0x09,
+ 0x22, 0xed, 0x0e, 0x61, 0x7c, 0x76, 0x31, 0x9c,
+ 0xbe, 0x27, 0xc9, 0xe6, 0x09, 0xc3, 0xc3, 0xc2,
+ 0xf4, 0xa2, 0x32, 0xba, 0x7c, 0xf2, 0x0f, 0xb8,
+ 0x3d, 0xcb, 0xe2, 0x4c, 0xc0, 0x7d, 0x8e, 0x5b,
+ 0x5a, 0xed, 0x05, 0x5c, 0x15, 0x96, 0x69, 0xc2,
+ 0x6f, 0x5f, 0x17, 0x03, 0x01, 0x00, 0x20, 0x5a,
+ 0xfe, 0x0b, 0xe1, 0x6f, 0xa8, 0x54, 0x19, 0x78,
+ 0xca, 0xba, 0x2e, 0x1e, 0x2e, 0xe1, 0x5d, 0x17,
+ 0xe5, 0x97, 0x05, 0x2c, 0x08, 0x0c, 0xff, 0xa8,
+ 0x59, 0xa9, 0xde, 0x5e, 0x21, 0x34, 0x04, 0x17,
+ 0x03, 0x01, 0x00, 0x30, 0x86, 0xb1, 0x3f, 0x88,
+ 0x43, 0xf0, 0x07, 0xee, 0xa8, 0xf4, 0xbc, 0xe7,
+ 0x5f, 0xc6, 0x8c, 0x86, 0x4c, 0xca, 0x70, 0x88,
+ 0xcc, 0x6a, 0xb4, 0x3d, 0x40, 0xe8, 0x54, 0x89,
+ 0x19, 0x43, 0x1f, 0x76, 0xe2, 0xac, 0xb2, 0x5b,
+ 0x92, 0xf8, 0x57, 0x39, 0x2a, 0xc3, 0x6d, 0x13,
+ 0x45, 0xfa, 0x36, 0x9e, 0x15, 0x03, 0x01, 0x00,
+ 0x20, 0x6d, 0xed, 0x7b, 0x59, 0x28, 0x2a, 0x27,
+ 0x04, 0x15, 0x07, 0x4e, 0xeb, 0x13, 0x00, 0xe3,
+ 0x3a, 0x3f, 0xf8, 0xaa, 0x2b, 0x3b, 0x1a, 0x8c,
+ 0x12, 0xd6, 0x4c, 0xec, 0x2a, 0xaf, 0x33, 0x60,
+ 0xaf,
},
}
var sslv3ServerScript = [][]byte{
{
- 0x16, 0x03, 0x00, 0x00, 0x41, 0x01, 0x00, 0x00,
- 0x3d, 0x03, 0x00, 0x4e, 0x70, 0xe2, 0x18, 0x86,
- 0xd6, 0xc6, 0x6f, 0xf3, 0xc8, 0xf4, 0x02, 0xd6,
- 0x4d, 0xee, 0x17, 0x32, 0x4b, 0xd2, 0x78, 0xd8,
- 0xa1, 0x03, 0x5d, 0x68, 0x82, 0x89, 0xbe, 0xfd,
- 0x12, 0xb9, 0x06, 0x00, 0x00, 0x16, 0x00, 0x33,
- 0x00, 0x39, 0x00, 0x16, 0x00, 0x32, 0x00, 0x38,
- 0x00, 0x13, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x0a,
- 0x00, 0x05, 0x00, 0x04, 0x01, 0x00,
+ 0x16, 0x03, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00,
+ 0x50, 0x03, 0x00, 0x50, 0x77, 0x3d, 0x42, 0xae,
+ 0x84, 0xbd, 0xc5, 0x07, 0xa5, 0xc4, 0xd6, 0x16,
+ 0x4e, 0xd5, 0xc5, 0xfa, 0x02, 0x7a, 0x0f, 0x1d,
+ 0xc1, 0xe1, 0xaa, 0xe3, 0x3b, 0x4b, 0x6f, 0x11,
+ 0xfa, 0x1a, 0xa4, 0x00, 0x00, 0x28, 0x00, 0x39,
+ 0x00, 0x38, 0x00, 0x35, 0x00, 0x16, 0x00, 0x13,
+ 0x00, 0x0a, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2f,
+ 0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12,
+ 0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08,
+ 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x02, 0x01,
+ 0x00,
},
-
{
0x16, 0x03, 0x00, 0x00, 0x2a, 0x02, 0x00, 0x00,
0x26, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -908,74 +1140,71 @@ var sslv3ServerScript = [][]byte{
0xbd, 0xd9, 0x16, 0x03, 0x00, 0x00, 0x04, 0x0e,
0x00, 0x00, 0x00,
},
-
{
0x16, 0x03, 0x00, 0x00, 0x84, 0x10, 0x00, 0x00,
- 0x80, 0x74, 0x0e, 0x3a, 0xcf, 0xba, 0x9f, 0x1a,
- 0x9b, 0xb2, 0xa4, 0xc7, 0x5d, 0xf3, 0x0c, 0x80,
- 0x06, 0x80, 0xf3, 0x57, 0xb2, 0xd9, 0x36, 0x24,
- 0x6a, 0x06, 0x13, 0x40, 0xf9, 0x7c, 0xb9, 0x3e,
- 0x4b, 0x68, 0x4f, 0x21, 0x90, 0x2d, 0xbd, 0xca,
- 0xd4, 0x83, 0xf0, 0x7a, 0xeb, 0x7a, 0x74, 0x1b,
- 0xcd, 0xfe, 0x69, 0xef, 0xc0, 0x86, 0xa0, 0x24,
- 0x31, 0x65, 0x40, 0xd2, 0xdd, 0x6f, 0xb9, 0xd7,
- 0x8d, 0xc1, 0x69, 0x60, 0x44, 0x7a, 0x75, 0xfb,
- 0x42, 0x6a, 0x0f, 0x66, 0x45, 0x10, 0x73, 0xee,
- 0x87, 0x28, 0x37, 0x83, 0x86, 0xd8, 0x5a, 0xc8,
- 0x60, 0x87, 0xda, 0x33, 0x87, 0xaf, 0x34, 0x8b,
- 0xf5, 0x61, 0x63, 0x7a, 0x5c, 0x60, 0x26, 0xb9,
- 0xdb, 0xa1, 0xb7, 0xe3, 0x60, 0x38, 0x94, 0x5c,
- 0x83, 0x23, 0xd6, 0x8d, 0xc2, 0x14, 0x4a, 0x0f,
- 0x0e, 0x4f, 0xf9, 0x4e, 0x7b, 0x15, 0xcd, 0x18,
- 0x04, 0x14, 0x03, 0x00, 0x00, 0x01, 0x01, 0x16,
- 0x03, 0x00, 0x00, 0x3c, 0xbd, 0xbc, 0xec, 0xdc,
- 0x79, 0xb1, 0xae, 0x16, 0xc9, 0x26, 0x9a, 0xc0,
- 0xc0, 0x2c, 0x33, 0x36, 0x13, 0x91, 0x58, 0x5d,
- 0x7d, 0xee, 0x4e, 0xd8, 0x7e, 0xac, 0x88, 0x87,
- 0x0a, 0x75, 0x66, 0xb1, 0x44, 0x79, 0x2f, 0x42,
- 0xe8, 0x92, 0x74, 0x4c, 0xab, 0x36, 0xc8, 0x17,
- 0x5f, 0x02, 0x8a, 0x20, 0x53, 0xe9, 0x1d, 0xb4,
- 0xfe, 0x5c, 0x2b, 0xd9, 0x0a, 0xfb, 0xc6, 0x63,
+ 0x80, 0x4a, 0x8d, 0xc4, 0x38, 0x7a, 0x9c, 0xd6,
+ 0xe8, 0x72, 0x9e, 0xa3, 0xdf, 0x37, 0xb4, 0x6c,
+ 0x58, 0x33, 0x59, 0xd9, 0xc9, 0x4b, 0x50, 0x33,
+ 0x6c, 0xed, 0x73, 0x38, 0x2a, 0x46, 0x55, 0x31,
+ 0xa9, 0x8e, 0x8e, 0xfc, 0x0b, 0x5d, 0x5f, 0x3c,
+ 0x88, 0x28, 0x3f, 0x60, 0x51, 0x13, 0xf1, 0x59,
+ 0x0c, 0xa3, 0x5e, 0xe0, 0xa3, 0x35, 0x06, 0xb1,
+ 0x71, 0x59, 0x24, 0x4e, 0xed, 0x07, 0x15, 0x88,
+ 0x50, 0xef, 0xc2, 0xb2, 0x2a, 0x52, 0x30, 0x6a,
+ 0x7c, 0xbe, 0x2f, 0xc6, 0x8f, 0xa8, 0x83, 0xc5,
+ 0x80, 0x14, 0x62, 0x74, 0x7f, 0x96, 0x9f, 0x41,
+ 0x32, 0x74, 0xdd, 0x76, 0x2d, 0x7b, 0xeb, 0x7b,
+ 0xea, 0xd0, 0x4f, 0x0c, 0xcf, 0x9a, 0x9c, 0xc5,
+ 0x7a, 0xe4, 0xbc, 0xf8, 0xa6, 0xe1, 0x09, 0x8e,
+ 0x7c, 0x53, 0x3a, 0xe3, 0x30, 0x8f, 0x76, 0xee,
+ 0x58, 0xbb, 0xfd, 0x0b, 0x06, 0xb8, 0xdf, 0xb7,
+ 0x31, 0x14, 0x03, 0x00, 0x00, 0x01, 0x01, 0x16,
+ 0x03, 0x00, 0x00, 0x3c, 0x13, 0x91, 0xc6, 0x4a,
+ 0x0c, 0x59, 0x25, 0xce, 0x54, 0xc0, 0x1d, 0xb9,
+ 0x2a, 0xff, 0x4d, 0xca, 0x26, 0x0c, 0x8c, 0x04,
+ 0x98, 0x7c, 0x7c, 0x38, 0xa3, 0xf5, 0xf9, 0x36,
+ 0x1c, 0x04, 0x32, 0x47, 0x2d, 0x48, 0x0e, 0x96,
+ 0xe8, 0x2b, 0x5e, 0x5a, 0xc6, 0x0a, 0x48, 0x41,
+ 0x34, 0x5e, 0x62, 0xd5, 0x68, 0x4e, 0x44, 0x1d,
+ 0xb2, 0xa1, 0x11, 0xad, 0x6e, 0x14, 0x85, 0x61,
},
-
{
0x14, 0x03, 0x00, 0x00, 0x01, 0x01, 0x16, 0x03,
- 0x00, 0x00, 0x3c, 0xaa, 0xa1, 0x98, 0xc4, 0x6b,
- 0x5a, 0x16, 0x3f, 0x5f, 0xa4, 0x96, 0x3e, 0x78,
- 0xe4, 0x6f, 0x49, 0x05, 0x47, 0xc4, 0x05, 0x60,
- 0xeb, 0x0b, 0x45, 0xe3, 0xbc, 0x50, 0x11, 0x24,
- 0x5f, 0x01, 0xd7, 0xb8, 0x8f, 0x60, 0x63, 0x66,
- 0xbd, 0x3e, 0xd9, 0xa8, 0x80, 0x43, 0x9f, 0x0b,
- 0x51, 0x61, 0xed, 0x13, 0xc6, 0x21, 0xd0, 0xfe,
- 0xbc, 0x17, 0x3c, 0x36, 0xb0, 0x82, 0x7f, 0x17,
- 0x03, 0x00, 0x00, 0x21, 0xee, 0x44, 0xf3, 0xa6,
- 0x88, 0x9d, 0x78, 0x44, 0xde, 0xdf, 0xeb, 0xc5,
- 0xad, 0xc4, 0xcc, 0x56, 0x5c, 0x54, 0x96, 0x52,
- 0x3f, 0xd9, 0x40, 0x6e, 0x79, 0xd8, 0x58, 0x78,
- 0x4f, 0x5a, 0xe9, 0x06, 0xef, 0x15, 0x03, 0x00,
- 0x00, 0x16, 0xd3, 0xc2, 0x52, 0x99, 0x2a, 0x84,
- 0xc4, 0x52, 0x5f, 0x3b, 0x19, 0xe7, 0xfc, 0x65,
- 0xaf, 0xd3, 0xb7, 0xa3, 0xcc, 0x4a, 0x1d, 0x2e,
+ 0x00, 0x00, 0x3c, 0x88, 0xae, 0xa9, 0xd4, 0xa8,
+ 0x10, 0x8d, 0x65, 0xa6, 0x3e, 0x1e, 0xed, 0xd2,
+ 0xfc, 0xc4, 0x7c, 0xa8, 0x94, 0x4f, 0x11, 0xaf,
+ 0xa6, 0x87, 0x09, 0x37, 0x54, 0xf7, 0x69, 0xd1,
+ 0xb5, 0x25, 0x6b, 0xb5, 0xed, 0xcb, 0x25, 0x39,
+ 0x73, 0xeb, 0x53, 0x6c, 0xc7, 0xb4, 0x29, 0x8f,
+ 0xd6, 0x49, 0xd1, 0x95, 0x59, 0x80, 0x9a, 0x67,
+ 0x5c, 0xb2, 0xe0, 0xbd, 0x1e, 0xff, 0xaa, 0x17,
+ 0x03, 0x00, 0x00, 0x21, 0x65, 0x7b, 0x99, 0x09,
+ 0x02, 0xc3, 0x9d, 0x54, 0xd6, 0xe7, 0x32, 0x62,
+ 0xab, 0xc1, 0x09, 0x91, 0x30, 0x0a, 0xc9, 0xfa,
+ 0x70, 0xec, 0x06, 0x7b, 0xa3, 0xe1, 0x5f, 0xb4,
+ 0x63, 0xe6, 0x5c, 0xba, 0x1f, 0x15, 0x03, 0x00,
+ 0x00, 0x16, 0x40, 0x70, 0xbe, 0xe6, 0xa6, 0xee,
+ 0x8f, 0xd0, 0x87, 0xa0, 0x43, 0xa1, 0x92, 0xd7,
+ 0xd0, 0x1a, 0x0c, 0x20, 0x7c, 0xbf, 0xa2, 0xb5,
},
}
var selectCertificateBySNIScript = [][]byte{
{
- 0x16, 0x03, 0x01, 0x00, 0x6e, 0x01, 0x00, 0x00,
- 0x6a, 0x03, 0x01, 0x4f, 0x85, 0xc4, 0xc2, 0xb9,
- 0x39, 0x80, 0x91, 0x66, 0x65, 0x56, 0x8e, 0xdd,
- 0x48, 0xe9, 0xca, 0x34, 0x02, 0x3c, 0xaf, 0x0d,
- 0x73, 0xb5, 0x2a, 0x05, 0x6e, 0xbd, 0x5e, 0x8f,
- 0x38, 0xf9, 0xe5, 0x00, 0x00, 0x28, 0x00, 0x39,
+ 0x16, 0x03, 0x01, 0x00, 0x6a, 0x01, 0x00, 0x00,
+ 0x66, 0x03, 0x01, 0x50, 0x77, 0x3d, 0xfe, 0xfb,
+ 0x8d, 0xc2, 0x68, 0xeb, 0xf9, 0xfa, 0x54, 0x97,
+ 0x86, 0x45, 0xa2, 0xa3, 0xed, 0xb1, 0x91, 0xb8,
+ 0x28, 0xc0, 0x47, 0xaf, 0xfb, 0xcd, 0xdc, 0x0e,
+ 0xb3, 0xea, 0xa5, 0x00, 0x00, 0x28, 0x00, 0x39,
0x00, 0x38, 0x00, 0x35, 0x00, 0x16, 0x00, 0x13,
0x00, 0x0a, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2f,
0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12,
0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08,
0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x02, 0x01,
- 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00,
0x0e, 0x00, 0x00, 0x0b, 0x73, 0x6e, 0x69, 0x74,
- 0x65, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x00,
- 0x23, 0x00, 0x00,
+ 0x65, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d,
},
{
0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
@@ -1053,632 +1282,684 @@ var selectCertificateBySNIScript = [][]byte{
},
{
0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
- 0x82, 0x00, 0x80, 0x70, 0x1d, 0x34, 0x75, 0xa2,
- 0xe7, 0xe3, 0x2f, 0x3d, 0xc1, 0x1d, 0xca, 0x0b,
- 0xe3, 0x64, 0xb9, 0x1a, 0x00, 0x69, 0xc4, 0x14,
- 0x05, 0x07, 0x7e, 0xc3, 0x51, 0x43, 0x52, 0x66,
- 0xe3, 0xbd, 0xff, 0x1b, 0x1a, 0x6a, 0x84, 0xf2,
- 0x07, 0x24, 0xd7, 0x12, 0xa8, 0x58, 0xcf, 0x8a,
- 0x50, 0x30, 0xe8, 0xc8, 0xb2, 0xf9, 0x58, 0x1c,
- 0x56, 0x53, 0x76, 0x21, 0xe0, 0x03, 0x7f, 0x77,
- 0xa7, 0xf1, 0xad, 0x67, 0xd4, 0xe2, 0x8f, 0xa0,
- 0x58, 0x6c, 0xe0, 0x28, 0x59, 0xf3, 0xd1, 0x53,
- 0x2b, 0x21, 0xbd, 0xa3, 0x84, 0x31, 0x73, 0xbf,
- 0x84, 0x0f, 0x83, 0xf4, 0xc4, 0xd0, 0xe5, 0x3c,
- 0x2d, 0x3e, 0xf2, 0x8a, 0x1e, 0xe7, 0xe9, 0x1f,
- 0x12, 0x13, 0xad, 0x29, 0xd6, 0x0c, 0xc7, 0xc6,
- 0x05, 0x53, 0x7d, 0x5e, 0xc6, 0x92, 0x72, 0xba,
- 0xd2, 0x93, 0x8f, 0x53, 0x84, 0x87, 0x44, 0x05,
- 0x9f, 0x5d, 0x66, 0x14, 0x03, 0x01, 0x00, 0x01,
- 0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xfc, 0x71,
- 0xaa, 0xa8, 0x37, 0xa8, 0xbd, 0x63, 0xb7, 0xbc,
- 0x95, 0xef, 0x0c, 0xcf, 0x39, 0x31, 0x93, 0xe6,
- 0x86, 0xbd, 0x3f, 0x56, 0x9d, 0xf0, 0xb2, 0xb5,
- 0xd1, 0xa7, 0xc6, 0x45, 0x89, 0x18, 0xfb, 0xa0,
- 0x7f, 0xc1,
+ 0x82, 0x00, 0x80, 0x69, 0xc3, 0xd4, 0x0e, 0xcc,
+ 0xdc, 0xbc, 0x5e, 0xc2, 0x64, 0xa6, 0xde, 0x3c,
+ 0x0c, 0x7e, 0x0c, 0x6b, 0x80, 0x0f, 0xd4, 0x8f,
+ 0x02, 0x4b, 0xb2, 0xba, 0x8d, 0x01, 0xeb, 0x6b,
+ 0xa1, 0x2e, 0x79, 0x37, 0xba, 0xae, 0x24, 0xc2,
+ 0x26, 0x72, 0x51, 0xe1, 0x82, 0x8e, 0x51, 0x41,
+ 0x1c, 0x54, 0xa4, 0x26, 0xbe, 0x13, 0xcd, 0x1b,
+ 0xc6, 0xed, 0x3d, 0x1f, 0xfd, 0x72, 0x80, 0x90,
+ 0xdb, 0xbf, 0xd6, 0x39, 0x94, 0x5f, 0x48, 0xfb,
+ 0x25, 0x5a, 0xc9, 0x60, 0x9b, 0xd7, 0xc6, 0x20,
+ 0xa8, 0x66, 0x64, 0x13, 0xf3, 0x65, 0xc8, 0xb1,
+ 0xd5, 0x33, 0x21, 0x0e, 0x73, 0x41, 0xc0, 0x18,
+ 0x1a, 0x37, 0xfe, 0xcf, 0x28, 0x2a, 0xcd, 0xe4,
+ 0x0b, 0xac, 0xdd, 0x25, 0x5e, 0xcb, 0x17, 0x51,
+ 0x69, 0xd5, 0x8c, 0xf4, 0xb6, 0x21, 0x98, 0xef,
+ 0x20, 0xdb, 0x14, 0x67, 0xf3, 0x7c, 0x95, 0x6a,
+ 0x48, 0x2a, 0x6a, 0x14, 0x03, 0x01, 0x00, 0x01,
+ 0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0x36, 0x1b,
+ 0x09, 0xe5, 0xb9, 0xb9, 0x4d, 0x7d, 0xae, 0x87,
+ 0xb6, 0x0f, 0xaf, 0xec, 0x22, 0xba, 0x0d, 0xa5,
+ 0x96, 0x5e, 0x64, 0x65, 0xe7, 0xfb, 0xe3, 0xf3,
+ 0x6b, 0x72, 0xa8, 0xdb, 0xed, 0xd8, 0x69, 0x9c,
+ 0x08, 0xd8,
},
{
0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
- 0x01, 0x00, 0x24, 0xb8, 0x6d, 0x9a, 0x90, 0x3c,
- 0x45, 0xe0, 0xff, 0x63, 0xba, 0xab, 0x3d, 0x7a,
- 0xa6, 0x49, 0x5a, 0x13, 0xdc, 0x0e, 0xa3, 0xba,
- 0x7f, 0x04, 0x19, 0x45, 0xfd, 0xfb, 0xbd, 0x00,
- 0xa3, 0xa7, 0x78, 0x81, 0x38, 0x9f, 0x10, 0x17,
- 0x03, 0x01, 0x00, 0x21, 0x43, 0xc3, 0x91, 0xb7,
- 0xbf, 0x50, 0x0b, 0x04, 0xb4, 0x5d, 0xc6, 0x20,
- 0x64, 0xb8, 0x01, 0x09, 0x25, 0x2c, 0x03, 0x30,
- 0xc0, 0x77, 0xc9, 0x5e, 0xe6, 0xe0, 0x99, 0xdc,
- 0xcd, 0x75, 0x9d, 0x51, 0x82, 0x15, 0x03, 0x01,
- 0x00, 0x16, 0x2d, 0x7a, 0x89, 0x7b, 0x36, 0x85,
- 0x2a, 0x93, 0xcb, 0x83, 0xa7, 0x2f, 0x9e, 0x91,
- 0xfc, 0xad, 0x57, 0xca, 0xf5, 0xbc, 0x13, 0x2f,
+ 0x01, 0x00, 0x24, 0x60, 0xf7, 0x09, 0x5f, 0xd1,
+ 0xcb, 0xc9, 0xe1, 0x22, 0xb5, 0x2a, 0xcc, 0xde,
+ 0x7c, 0xa7, 0xb8, 0x85, 0x00, 0xbc, 0xfd, 0x85,
+ 0xe1, 0x91, 0x36, 0xbb, 0x07, 0x42, 0xad, 0x3d,
+ 0x29, 0x62, 0x69, 0xc1, 0x45, 0x92, 0x6f, 0x17,
+ 0x03, 0x01, 0x00, 0x21, 0x0d, 0xf9, 0xd5, 0x87,
+ 0xb9, 0x57, 0x3c, 0x50, 0x19, 0xe4, 0x3a, 0x50,
+ 0x45, 0xcc, 0x86, 0x89, 0xd4, 0x32, 0x79, 0x45,
+ 0x7c, 0x9f, 0x96, 0xd4, 0x54, 0x56, 0x0c, 0x63,
+ 0x72, 0x81, 0xc3, 0xd3, 0xe3, 0x15, 0x03, 0x01,
+ 0x00, 0x16, 0x84, 0xec, 0x2e, 0xf6, 0xaf, 0x4f,
+ 0xee, 0x48, 0x0f, 0xbe, 0xcd, 0x82, 0x5c, 0x56,
+ 0x16, 0xe4, 0xfb, 0x89, 0xc5, 0x57, 0x3e, 0x91,
},
}
-var clientauthTests = []clientauthTest{
- // Server doesn't asks for cert
- // go test -run "TestRunServer" -serve -clientauth 0
- // gnutls-cli --insecure --debug 100 -p 10443 localhost 2>&1 |
- // python parse-gnutls-cli-debug-log.py
- {"NoClientCert", NoClientCert, nil,
- [][]byte{{
- 0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
- 0x76, 0x03, 0x02, 0x4e, 0xe0, 0x92, 0x5d, 0xcd,
- 0xfe, 0x0c, 0x69, 0xd4, 0x7d, 0x8e, 0xa6, 0x88,
- 0xde, 0x72, 0x04, 0x29, 0x6a, 0x4a, 0x16, 0x23,
- 0xd7, 0x8f, 0xbc, 0xfa, 0x80, 0x73, 0x2e, 0x12,
- 0xb7, 0x0b, 0x39, 0x00, 0x00, 0x34, 0x00, 0x33,
- 0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
- 0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
- 0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
- 0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
- 0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
- 0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
- 0x00, 0x8a, 0x01, 0x00, 0x00, 0x19, 0x00, 0x09,
- 0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
- 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
- },
+var issueSessionTicketTest = [][]byte{
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x5a, 0x01, 0x00, 0x00,
+ 0x56, 0x03, 0x01, 0x50, 0x77, 0x3e, 0x49, 0x7a,
+ 0xb7, 0x86, 0x5c, 0x27, 0xd2, 0x97, 0x61, 0xe3,
+ 0x49, 0x41, 0x48, 0xe7, 0x0e, 0xaa, 0x7e, 0x4d,
+ 0xb8, 0xdc, 0x01, 0x97, 0xfb, 0xab, 0x53, 0xb2,
+ 0x5e, 0x36, 0xf6, 0x00, 0x00, 0x28, 0x00, 0x39,
+ 0x00, 0x38, 0x00, 0x35, 0x00, 0x16, 0x00, 0x13,
+ 0x00, 0x0a, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2f,
+ 0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12,
+ 0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08,
+ 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x02, 0x01,
+ 0x00, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x30, 0x02, 0x00, 0x00,
+ 0x2c, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
+ 0x04, 0x00, 0x23, 0x00, 0x00, 0x16, 0x03, 0x01,
+ 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba, 0x00, 0x02,
+ 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82, 0x02, 0xb0,
+ 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03, 0x02, 0x01,
+ 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0, 0xbb, 0xa4,
+ 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x05, 0x05, 0x00, 0x30, 0x45, 0x31, 0x0b, 0x30,
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
+ 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d,
+ 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
+ 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
+ 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69,
+ 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c,
+ 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30,
+ 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39,
+ 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30,
+ 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, 0x33,
+ 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41,
+ 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
+ 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65,
+ 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21,
+ 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+ 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
+ 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74,
+ 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74,
+ 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30,
+ 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0x79,
+ 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf, 0x46, 0x10,
+ 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b, 0x07, 0x43,
+ 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a, 0x43, 0x85,
+ 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65, 0x4c, 0x2c,
+ 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4, 0x82, 0xe5,
+ 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62, 0xa5, 0x2c,
+ 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c, 0x7a, 0x56,
+ 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58, 0x7b, 0x26,
+ 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0, 0xc9, 0x21,
+ 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f, 0x5a, 0xbf,
+ 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18, 0x99, 0x07,
+ 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1, 0x04, 0x39,
+ 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9, 0x7c, 0xe3,
+ 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01, 0xcf, 0xaf,
+ 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d, 0xdb, 0xdb,
+ 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79, 0x02, 0x03,
+ 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81,
+ 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad, 0xe2, 0x85,
+ 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, 0x23,
+ 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, 0x39,
+ 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04,
+ 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1, 0xad, 0xe2,
+ 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce,
+ 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88,
+ 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+ 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+ 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+ 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+ 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0x85,
+ 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30,
+ 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05,
+ 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00,
+ 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b, 0xb1, 0x59,
+ 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0, 0x14, 0xd7,
+ 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5, 0x5a, 0x95,
+ 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae, 0x12, 0x66,
+ 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e, 0x60, 0xd3,
+ 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5, 0x25, 0x13,
+ 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30, 0x1d, 0xba,
+ 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7, 0xd7, 0x31,
+ 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78, 0xea, 0x50,
+ 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d, 0x5a, 0x5f,
+ 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75, 0x90, 0x96,
+ 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd, 0x98, 0x1f,
+ 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c, 0xa3, 0x1b,
+ 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57, 0xe9, 0x70,
+ 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b, 0x26, 0x6e,
+ 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7, 0xbd, 0xd9,
+ 0x16, 0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00,
+ 0x00,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
+ 0x82, 0x00, 0x80, 0x68, 0x10, 0xdc, 0x80, 0xbc,
+ 0xb3, 0x5a, 0x10, 0x75, 0x89, 0xcc, 0xe5, 0x9f,
+ 0xbf, 0xe2, 0xce, 0xa4, 0x9f, 0x7f, 0x60, 0xc4,
+ 0xfe, 0x5c, 0xb5, 0x02, 0x2d, 0xa5, 0xa9, 0x1e,
+ 0x2c, 0x10, 0x79, 0x15, 0x0f, 0xed, 0x96, 0xb3,
+ 0xa8, 0x5e, 0x21, 0xbc, 0x5b, 0xdc, 0x58, 0x04,
+ 0x7d, 0x37, 0xdb, 0xa0, 0x31, 0xe8, 0x4f, 0x04,
+ 0xbc, 0x46, 0x7c, 0xdb, 0x2e, 0x93, 0x07, 0xaf,
+ 0xa6, 0x36, 0xd3, 0x39, 0x8d, 0x1d, 0x95, 0xa8,
+ 0x50, 0x4b, 0xc4, 0x2b, 0xde, 0xd7, 0x04, 0x6d,
+ 0x77, 0x6c, 0x4d, 0x70, 0x51, 0x88, 0x16, 0x31,
+ 0x40, 0xb5, 0xba, 0x90, 0x47, 0x64, 0x0c, 0x87,
+ 0xa5, 0x19, 0xf9, 0x89, 0x24, 0x3c, 0x5e, 0x4b,
+ 0xaa, 0xe0, 0x60, 0x47, 0x0f, 0x2e, 0xcc, 0xc2,
+ 0xd5, 0x21, 0xed, 0x72, 0xd0, 0xa9, 0xdd, 0x2a,
+ 0x2b, 0xef, 0x08, 0x3a, 0x65, 0xea, 0x8b, 0x52,
+ 0x77, 0x2d, 0xcc, 0x14, 0x03, 0x01, 0x00, 0x01,
+ 0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xe2, 0x95,
+ 0x62, 0x3c, 0x18, 0xe5, 0xc7, 0x2c, 0xda, 0x16,
+ 0x9b, 0x28, 0x0d, 0xf7, 0x88, 0x7b, 0x5d, 0x33,
+ 0x55, 0x3b, 0x01, 0x73, 0xf2, 0xc6, 0x4e, 0x96,
+ 0x01, 0x01, 0x83, 0x65, 0xd4, 0xef, 0x12, 0x13,
+ 0x1d, 0x42,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x72, 0x04, 0x00, 0x00,
+ 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65,
+ 0xe8, 0x4b, 0xd1, 0xef, 0xba, 0xfb, 0x41, 0x92,
+ 0x6d, 0x37, 0x5f, 0xf8, 0x7d, 0x90, 0x0f, 0x01,
+ 0xf8, 0x8c, 0xee, 0xbc, 0xd9, 0x0c, 0x97, 0x7e,
+ 0x23, 0x46, 0xe2, 0x6b, 0x52, 0xc6, 0xc6, 0x97,
+ 0x1d, 0xab, 0xde, 0xa0, 0x86, 0x94, 0xc8, 0x2e,
+ 0x8b, 0x2e, 0x42, 0x5f, 0xc2, 0x70, 0x35, 0xc9,
+ 0xee, 0x37, 0xeb, 0x70, 0xaa, 0x59, 0x23, 0x6c,
+ 0xc8, 0xc1, 0x84, 0x89, 0x39, 0x87, 0x73, 0x0a,
+ 0x7e, 0xba, 0xca, 0xed, 0x63, 0xba, 0x4e, 0x4f,
+ 0xf3, 0x31, 0x4b, 0xf0, 0xee, 0x91, 0xa5, 0xb4,
+ 0x62, 0x01, 0x9e, 0xbd, 0xbc, 0xb3, 0x35, 0x14,
+ 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01,
+ 0x00, 0x24, 0x3f, 0x66, 0xe4, 0x98, 0xc1, 0x3f,
+ 0xc6, 0x2c, 0x81, 0xfb, 0xa9, 0x9f, 0x27, 0xe9,
+ 0x63, 0x20, 0x1e, 0x0e, 0x4f, 0xfc, 0x5d, 0x12,
+ 0xee, 0x77, 0x73, 0xc6, 0x96, 0x51, 0xf2, 0x26,
+ 0x35, 0x3f, 0xce, 0x6a, 0xa9, 0xfd, 0x17, 0x03,
+ 0x01, 0x00, 0x21, 0x8d, 0xd5, 0x67, 0x60, 0x5d,
+ 0xa7, 0x93, 0xcc, 0x39, 0x78, 0x59, 0xab, 0xdb,
+ 0x10, 0x96, 0xf2, 0xad, 0xa2, 0x85, 0xe2, 0x93,
+ 0x43, 0x43, 0xcf, 0x82, 0xbd, 0x1f, 0xdc, 0x7a,
+ 0x72, 0xd6, 0x83, 0x3b, 0x15, 0x03, 0x01, 0x00,
+ 0x16, 0x89, 0x55, 0xf6, 0x42, 0x71, 0xa9, 0xe9,
+ 0x05, 0x68, 0xe8, 0xce, 0x0d, 0x21, 0xe9, 0xec,
+ 0xf2, 0x27, 0x67, 0xa7, 0x94, 0xf8, 0x34,
+ },
+}
+var serverResumeTest = [][]byte{
+ {
+ 0x16, 0x03, 0x01, 0x00, 0xc2, 0x01, 0x00, 0x00,
+ 0xbe, 0x03, 0x01, 0x50, 0x77, 0x3e, 0x4f, 0x1f,
+ 0x6f, 0xa5, 0x81, 0xeb, 0xb8, 0x80, 0x55, 0xa4,
+ 0x76, 0xc2, 0x7f, 0x27, 0xf2, 0xe7, 0xc9, 0x7a,
+ 0x01, 0x3c, 0xd8, 0xc1, 0xde, 0x99, 0x1f, 0x7c,
+ 0xab, 0x35, 0x98, 0x00, 0x00, 0x28, 0x00, 0x39,
+ 0x00, 0x38, 0x00, 0x35, 0x00, 0x16, 0x00, 0x13,
+ 0x00, 0x0a, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2f,
+ 0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12,
+ 0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08,
+ 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x02, 0x01,
+ 0x00, 0x00, 0x6c, 0x00, 0x23, 0x00, 0x68, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65,
+ 0xe8, 0x4b, 0xd1, 0xef, 0xba, 0xfb, 0x41, 0x92,
+ 0x6d, 0x37, 0x5f, 0xf8, 0x7d, 0x90, 0x0f, 0x01,
+ 0xf8, 0x8c, 0xee, 0xbc, 0xd9, 0x0c, 0x97, 0x7e,
+ 0x23, 0x46, 0xe2, 0x6b, 0x52, 0xc6, 0xc6, 0x97,
+ 0x1d, 0xab, 0xde, 0xa0, 0x86, 0x94, 0xc8, 0x2e,
+ 0x8b, 0x2e, 0x42, 0x5f, 0xc2, 0x70, 0x35, 0xc9,
+ 0xee, 0x37, 0xeb, 0x70, 0xaa, 0x59, 0x23, 0x6c,
+ 0xc8, 0xc1, 0x84, 0x89, 0x39, 0x87, 0x73, 0x0a,
+ 0x7e, 0xba, 0xca, 0xed, 0x63, 0xba, 0x4e, 0x4f,
+ 0xf3, 0x31, 0x4b, 0xf0, 0xee, 0x91, 0xa5, 0xb4,
+ 0x62, 0x01, 0x9e, 0xbd, 0xbc, 0xb3, 0x35,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
+ 0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x14,
+ 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01,
+ 0x00, 0x24, 0xc5, 0x35, 0x74, 0x19, 0x05, 0xc5,
+ 0x85, 0x68, 0x48, 0xe8, 0xb5, 0xe9, 0xaf, 0x78,
+ 0xbd, 0x35, 0x6f, 0xe9, 0x79, 0x34, 0x1b, 0xf0,
+ 0x35, 0xd4, 0x4e, 0x55, 0x2e, 0x3c, 0xd5, 0xaf,
+ 0xfc, 0xba, 0xf5, 0x1e, 0x83, 0x32,
+ },
+ {
+ 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+ 0x01, 0x00, 0x24, 0x27, 0x28, 0x88, 0xe1, 0x7e,
+ 0x0d, 0x9c, 0x12, 0x50, 0xf6, 0x7a, 0xa7, 0x32,
+ 0x21, 0x68, 0xba, 0xd8, 0x0a, 0xdc, 0x39, 0xef,
+ 0x68, 0x95, 0x82, 0xae, 0xbd, 0x12, 0x79, 0xa1,
+ 0x99, 0xfd, 0xd0, 0x10, 0x8e, 0x4b, 0xd8,
+ },
+ {
+ 0x17, 0x03, 0x01, 0x00, 0x21, 0xc5, 0x7e, 0x0a,
+ 0x52, 0x6a, 0xb9, 0xaa, 0x1d, 0xae, 0x9e, 0x24,
+ 0x9c, 0x34, 0x1e, 0xdb, 0x50, 0x95, 0xee, 0x76,
+ 0xd7, 0x28, 0x88, 0x08, 0xe3, 0x2e, 0x58, 0xf7,
+ 0xdb, 0x34, 0x75, 0xa5, 0x7f, 0x9d, 0x15, 0x03,
+ 0x01, 0x00, 0x16, 0x2c, 0xc1, 0x29, 0x5f, 0x12,
+ 0x1d, 0x19, 0xab, 0xb3, 0xf4, 0x35, 0x1c, 0x62,
+ 0x6a, 0x80, 0x29, 0x0d, 0x0e, 0xef, 0x7d, 0x6e,
+ 0x50,
+ },
+}
- {
- 0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
- 0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
- 0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
- 0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
- 0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
- 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
- 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
- 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
- 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
- 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
- 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
- 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
- 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
- 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
- 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
- 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
- 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
- 0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
- 0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
- 0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
- 0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
- 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
- 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
- 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
- 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
- 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
- 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
- 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
- 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
- 0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
- 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
- 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
- 0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
- 0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
- 0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
- 0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
- 0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
- 0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
- 0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
- 0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
- 0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
- 0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
- 0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
- 0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
- 0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
- 0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
- 0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
- 0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
- 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
- 0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
- 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
- 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
- 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
- 0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
- 0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
- 0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
- 0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
- 0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
- 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
- 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
- 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
- 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
- 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
- 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
- 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
- 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
- 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
- 0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
- 0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
- 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
- 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
- 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
- 0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
- 0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
- 0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
- 0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
- 0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
- 0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
- 0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
- 0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
- 0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
- 0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
- 0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
- 0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
- 0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
- 0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
- 0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
- 0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
- 0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x04, 0x0e,
- 0x00, 0x00, 0x00,
- },
-
- {
- 0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
- 0x82, 0x00, 0x80, 0x10, 0xe1, 0x00, 0x3d, 0x0a,
- 0x6b, 0x02, 0x7f, 0x97, 0xde, 0xfb, 0x65, 0x46,
- 0x1a, 0x50, 0x4e, 0x34, 0x9a, 0xae, 0x14, 0x7e,
- 0xec, 0xef, 0x85, 0x15, 0x3b, 0x39, 0xc2, 0x45,
- 0x04, 0x40, 0x92, 0x71, 0xd6, 0x7e, 0xf6, 0xfd,
- 0x4d, 0x84, 0xf7, 0xc4, 0x77, 0x99, 0x3d, 0xe2,
- 0xc3, 0x8d, 0xb0, 0x4c, 0x74, 0xc8, 0x51, 0xec,
- 0xb2, 0xe8, 0x6b, 0xa1, 0xd2, 0x4d, 0xd8, 0x61,
- 0x92, 0x7a, 0x24, 0x57, 0x44, 0x4f, 0xa2, 0x1e,
- 0x74, 0x0b, 0x06, 0x4b, 0x80, 0x34, 0x8b, 0xfe,
- 0xc2, 0x0e, 0xc1, 0xcd, 0xab, 0x0c, 0x3f, 0x54,
- 0xe2, 0x44, 0xe9, 0x6c, 0x2b, 0xba, 0x7b, 0x64,
- 0xf1, 0x93, 0x65, 0x75, 0xf2, 0x35, 0xff, 0x27,
- 0x03, 0xd5, 0x64, 0xe6, 0x8e, 0xe7, 0x7b, 0x56,
- 0xb6, 0x61, 0x73, 0xeb, 0xa2, 0xdc, 0xa4, 0x6e,
- 0x52, 0xac, 0xbc, 0xba, 0x11, 0xa3, 0xd2, 0x61,
- 0x4a, 0xe0, 0xbb, 0x14, 0x03, 0x01, 0x00, 0x01,
- 0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xd2, 0x5a,
- 0x0c, 0x2a, 0x27, 0x96, 0xba, 0xa9, 0x67, 0xd2,
- 0x51, 0x68, 0x32, 0x68, 0x22, 0x1f, 0xb9, 0x27,
- 0x79, 0x59, 0x28, 0xdf, 0x38, 0x1f, 0x92, 0x21,
- 0x5d, 0x0f, 0xf4, 0xc0, 0xee, 0xb7, 0x10, 0x5a,
- 0xa9, 0x45,
- },
-
- {
- 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
- 0x01, 0x00, 0x24, 0x13, 0x6f, 0x6c, 0x71, 0x83,
- 0x59, 0xcf, 0x32, 0x72, 0xe9, 0xce, 0xcc, 0x7a,
- 0x6c, 0xf0, 0x72, 0x39, 0x16, 0xae, 0x40, 0x61,
- 0xfa, 0x92, 0x4c, 0xe7, 0xf2, 0x1a, 0xd7, 0x0c,
- 0x84, 0x76, 0x6c, 0xe9, 0x11, 0x43, 0x19, 0x17,
- 0x03, 0x01, 0x00, 0x21, 0xc0, 0xa2, 0x13, 0x28,
- 0x94, 0x8c, 0x5c, 0xd6, 0x79, 0xb9, 0xfe, 0xae,
- 0x45, 0x4b, 0xc0, 0x7c, 0xae, 0x2d, 0xb4, 0x0d,
- 0x31, 0xc4, 0xad, 0x22, 0xd7, 0x1e, 0x99, 0x1c,
- 0x4c, 0x69, 0xab, 0x42, 0x61, 0x15, 0x03, 0x01,
- 0x00, 0x16, 0xe1, 0x0c, 0x67, 0xf3, 0xf4, 0xb9,
- 0x8e, 0x81, 0x8e, 0x01, 0xb8, 0xa0, 0x69, 0x8c,
- 0x03, 0x11, 0x43, 0x3e, 0xee, 0xb7, 0x4d, 0x69,
- }}},
+var clientauthTests = []clientauthTest{
// Server asks for cert with empty CA list, client doesn't give it.
// go test -run "TestRunServer" -serve -clientauth 1
- // gnutls-cli --insecure --debug 100 -p 10443 localhost
- {"RequestClientCert, none given", RequestClientCert, nil,
- [][]byte{{
- 0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
- 0x76, 0x03, 0x02, 0x4e, 0xe0, 0x93, 0xe2, 0x47,
- 0x06, 0xa0, 0x61, 0x0c, 0x51, 0xdd, 0xf0, 0xef,
- 0xf4, 0x30, 0x72, 0xe1, 0xa6, 0x50, 0x68, 0x82,
- 0x3c, 0xfb, 0xcb, 0x72, 0x5e, 0x73, 0x9d, 0xda,
- 0x27, 0x35, 0x72, 0x00, 0x00, 0x34, 0x00, 0x33,
- 0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
- 0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
- 0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
- 0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
- 0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
- 0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
- 0x00, 0x8a, 0x01, 0x00, 0x00, 0x19, 0x00, 0x09,
- 0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
- 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
+ {"RequestClientCert, none given", RequestClientCert, nil, [][]byte{
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x54, 0x01, 0x00, 0x00,
+ 0x50, 0x03, 0x01, 0x50, 0x77, 0x43, 0x9e, 0x31,
+ 0xe6, 0x36, 0x5e, 0x5e, 0x24, 0xe4, 0x0d, 0x26,
+ 0x34, 0xa7, 0x1c, 0x2e, 0x59, 0x6d, 0xa5, 0x3e,
+ 0x72, 0xf3, 0xa3, 0x1c, 0xbc, 0xb3, 0x27, 0xaf,
+ 0x92, 0x5b, 0x7d, 0x00, 0x00, 0x28, 0x00, 0x39,
+ 0x00, 0x38, 0x00, 0x35, 0x00, 0x16, 0x00, 0x13,
+ 0x00, 0x0a, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2f,
+ 0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12,
+ 0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08,
+ 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x02, 0x01,
+ 0x00,
},
-
- {
- 0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
- 0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
- 0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
- 0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
- 0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
- 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
- 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
- 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
- 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
- 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
- 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
- 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
- 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
- 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
- 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
- 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
- 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
- 0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
- 0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
- 0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
- 0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
- 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
- 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
- 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
- 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
- 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
- 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
- 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
- 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
- 0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
- 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
- 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
- 0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
- 0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
- 0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
- 0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
- 0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
- 0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
- 0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
- 0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
- 0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
- 0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
- 0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
- 0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
- 0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
- 0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
- 0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
- 0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
- 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
- 0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
- 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
- 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
- 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
- 0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
- 0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
- 0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
- 0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
- 0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
- 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
- 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
- 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
- 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
- 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
- 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
- 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
- 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
- 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
- 0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
- 0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
- 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
- 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
- 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
- 0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
- 0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
- 0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
- 0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
- 0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
- 0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
- 0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
- 0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
- 0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
- 0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
- 0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
- 0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
- 0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
- 0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
- 0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
- 0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
- 0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x08, 0x0d,
- 0x00, 0x00, 0x04, 0x01, 0x01, 0x00, 0x00, 0x16,
- 0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
- },
-
- {
- 0x16, 0x03, 0x01, 0x00, 0x07, 0x0b, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x16, 0x03, 0x01, 0x00,
- 0x86, 0x10, 0x00, 0x00, 0x82, 0x00, 0x80, 0x64,
- 0x28, 0xb9, 0x3f, 0x48, 0xaf, 0x06, 0x22, 0x39,
- 0x56, 0xd8, 0x6f, 0x63, 0x5d, 0x03, 0x48, 0x63,
- 0x01, 0x13, 0xa2, 0xd6, 0x76, 0xc0, 0xab, 0xda,
- 0x25, 0x30, 0x75, 0x6c, 0xaa, 0xb4, 0xdc, 0x35,
- 0x72, 0xdc, 0xf2, 0x43, 0xe4, 0x1d, 0x82, 0xfb,
- 0x6c, 0x64, 0xe2, 0xa7, 0x8f, 0x32, 0x67, 0x6b,
- 0xcd, 0xd2, 0xb2, 0x36, 0x94, 0xbc, 0x6f, 0x46,
- 0x79, 0x29, 0x42, 0xe3, 0x1a, 0xbf, 0xfb, 0x41,
- 0xd5, 0xe3, 0xb4, 0x2a, 0xf6, 0x95, 0x6f, 0x0c,
- 0x87, 0xb9, 0x03, 0x18, 0xa1, 0xea, 0x4a, 0xe2,
- 0x2e, 0x0f, 0x50, 0x00, 0xc1, 0xe8, 0x8c, 0xc8,
- 0xa2, 0xf6, 0xa4, 0x05, 0xf4, 0x38, 0x3e, 0xd9,
- 0x6e, 0x63, 0x96, 0x0c, 0x34, 0x73, 0x90, 0x03,
- 0x55, 0xa6, 0x34, 0xb0, 0x5e, 0x8c, 0x48, 0x40,
- 0x25, 0x45, 0x84, 0xa6, 0x21, 0x3f, 0x81, 0x97,
- 0xa7, 0x11, 0x09, 0x14, 0x95, 0xa5, 0xe5, 0x14,
- 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01,
- 0x00, 0x24, 0x16, 0xaa, 0x01, 0x2c, 0xa8, 0xc1,
- 0x28, 0xaf, 0x35, 0xc1, 0xc1, 0xf3, 0x0a, 0x25,
- 0x66, 0x6e, 0x27, 0x11, 0xa3, 0xa4, 0xd9, 0xe9,
- 0xea, 0x15, 0x09, 0x9d, 0x28, 0xe3, 0x5b, 0x2b,
- 0xa6, 0x25, 0xa7, 0x14, 0x24, 0x3a,
- },
-
- {
- 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
- 0x01, 0x00, 0x24, 0x9a, 0xa8, 0xd6, 0x77, 0x46,
- 0x45, 0x68, 0x9d, 0x5d, 0xa9, 0x68, 0x03, 0xe5,
- 0xaf, 0xe8, 0xc8, 0x21, 0xc5, 0xc6, 0xc1, 0x50,
- 0xe0, 0xd8, 0x52, 0xce, 0xa3, 0x4f, 0x2d, 0xf4,
- 0xe3, 0xa7, 0x7d, 0x35, 0x80, 0x84, 0x12, 0x17,
- 0x03, 0x01, 0x00, 0x21, 0x8a, 0x82, 0x0c, 0x54,
- 0x1b, 0xeb, 0x77, 0x90, 0x2c, 0x3e, 0xbc, 0xf0,
- 0x23, 0xcc, 0xa8, 0x9f, 0x25, 0x08, 0x12, 0xed,
- 0x43, 0xf1, 0xf9, 0x06, 0xad, 0xa9, 0x4b, 0x97,
- 0x82, 0xb7, 0xc4, 0x0b, 0x4c, 0x15, 0x03, 0x01,
- 0x00, 0x16, 0x05, 0x2d, 0x9d, 0x45, 0x03, 0xb7,
- 0xc2, 0xd1, 0xb5, 0x1a, 0x43, 0xcf, 0x1a, 0x37,
- 0xf4, 0x70, 0xcc, 0xb4, 0xed, 0x07, 0x76, 0x3a,
- }}},
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
+ 0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
+ 0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
+ 0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
+ 0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
+ 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+ 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+ 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+ 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+ 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
+ 0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
+ 0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
+ 0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
+ 0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
+ 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
+ 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
+ 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+ 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
+ 0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+ 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
+ 0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
+ 0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
+ 0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
+ 0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
+ 0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
+ 0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
+ 0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
+ 0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
+ 0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
+ 0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
+ 0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
+ 0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
+ 0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
+ 0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
+ 0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
+ 0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
+ 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
+ 0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
+ 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
+ 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
+ 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
+ 0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
+ 0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
+ 0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
+ 0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
+ 0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
+ 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
+ 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
+ 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
+ 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
+ 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
+ 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
+ 0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
+ 0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+ 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
+ 0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
+ 0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
+ 0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
+ 0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
+ 0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
+ 0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
+ 0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
+ 0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
+ 0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
+ 0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
+ 0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
+ 0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
+ 0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
+ 0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
+ 0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
+ 0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
+ 0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x08, 0x0d,
+ 0x00, 0x00, 0x04, 0x01, 0x01, 0x00, 0x00, 0x16,
+ 0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x07, 0x0b, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x16, 0x03, 0x01, 0x00,
+ 0x86, 0x10, 0x00, 0x00, 0x82, 0x00, 0x80, 0x04,
+ 0x58, 0x63, 0x26, 0x32, 0x1b, 0x34, 0xbe, 0x10,
+ 0xe4, 0xe4, 0x3e, 0xcd, 0x36, 0x7f, 0xa8, 0xa8,
+ 0xe0, 0x19, 0xe8, 0x94, 0x13, 0xd9, 0x35, 0xc4,
+ 0x71, 0xb4, 0x91, 0xd4, 0xbc, 0x74, 0x57, 0x9f,
+ 0x93, 0xb7, 0x5d, 0x3b, 0x9c, 0xff, 0x5d, 0x79,
+ 0xdb, 0x86, 0xfc, 0xdc, 0x74, 0x1e, 0x0c, 0xc6,
+ 0xe8, 0x93, 0xcf, 0xaf, 0xba, 0x1d, 0xfd, 0x8a,
+ 0xeb, 0xef, 0xbf, 0xfa, 0xa6, 0xe7, 0x53, 0x98,
+ 0x60, 0x4e, 0x0e, 0x60, 0x7d, 0xea, 0x40, 0x8d,
+ 0x1d, 0x8f, 0xa3, 0xc6, 0x83, 0xbc, 0xef, 0xb7,
+ 0x9a, 0x4a, 0xe7, 0x99, 0xee, 0x0b, 0xc7, 0x46,
+ 0x75, 0x45, 0x66, 0xe8, 0x5f, 0x4b, 0x08, 0xa4,
+ 0xc1, 0x36, 0xd0, 0x36, 0x2c, 0xf2, 0x9a, 0x44,
+ 0x1e, 0x5f, 0x22, 0xf4, 0xbe, 0x66, 0x66, 0x17,
+ 0xd8, 0xb6, 0x0a, 0x89, 0xed, 0x22, 0x80, 0xdb,
+ 0xad, 0x05, 0xd1, 0xb5, 0x93, 0xa1, 0x1c, 0x14,
+ 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01,
+ 0x00, 0x24, 0x62, 0x6f, 0x3d, 0x30, 0x56, 0x97,
+ 0xde, 0x03, 0x67, 0xa9, 0x63, 0x21, 0xb6, 0xe6,
+ 0x05, 0x69, 0x94, 0xfb, 0x50, 0xc1, 0x99, 0xdd,
+ 0xf6, 0xe8, 0x60, 0xbd, 0xe6, 0xba, 0xe3, 0x50,
+ 0x0a, 0xcd, 0xde, 0x14, 0x16, 0xc4,
+ },
+ {
+ 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+ 0x01, 0x00, 0x24, 0xf0, 0x21, 0xf6, 0x84, 0x6a,
+ 0xe3, 0x6b, 0x8a, 0xc5, 0x46, 0x50, 0xca, 0x40,
+ 0xea, 0x4e, 0x82, 0xc1, 0x70, 0x25, 0xd8, 0x7d,
+ 0x60, 0xf5, 0x51, 0x7f, 0x64, 0x03, 0x9f, 0x53,
+ 0xec, 0xfb, 0x57, 0xa9, 0xfc, 0x26, 0x15, 0x17,
+ 0x03, 0x01, 0x00, 0x21, 0xa6, 0xc6, 0x94, 0x2b,
+ 0xa9, 0xcb, 0x93, 0xff, 0xb6, 0xa6, 0xe7, 0xc5,
+ 0x37, 0x86, 0x15, 0x37, 0x57, 0xce, 0xef, 0x54,
+ 0x96, 0x5d, 0x50, 0xa0, 0x50, 0x69, 0x5e, 0x82,
+ 0x61, 0x8d, 0x42, 0xfb, 0x78, 0x15, 0x03, 0x01,
+ 0x00, 0x16, 0x45, 0xd1, 0x86, 0x68, 0x59, 0xc1,
+ 0xaf, 0xac, 0x5c, 0x46, 0x8a, 0x68, 0x69, 0x0c,
+ 0xd7, 0x67, 0xbf, 0xf0, 0x3e, 0xee, 0x45, 0x55,
+ },
+ }},
// Server asks for cert with empty CA list, client gives one
// go test -run "TestRunServer" -serve -clientauth 1
- // gnutls-cli --insecure --debug 100 -p 10443 localhost
- {"RequestClientCert, client gives it", RequestClientCert,
- []*x509.Certificate{clientCertificate},
- [][]byte{{
- 0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
- 0x76, 0x03, 0x02, 0x4e, 0xe7, 0x44, 0xda, 0x58,
- 0x7d, 0x46, 0x4a, 0x48, 0x97, 0x9f, 0xe5, 0x91,
- 0x11, 0x64, 0xa7, 0x1e, 0x4d, 0xb7, 0xfe, 0x9b,
- 0xc6, 0x63, 0xf8, 0xa4, 0xb5, 0x0b, 0x18, 0xb5,
- 0xbd, 0x19, 0xb3, 0x00, 0x00, 0x34, 0x00, 0x33,
- 0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
- 0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
- 0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
- 0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
- 0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
- 0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
- 0x00, 0x8a, 0x01, 0x00, 0x00, 0x19, 0x00, 0x09,
- 0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
- 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
+ {"RequestClientCert, client gives it", RequestClientCert, []*x509.Certificate{clientCertificate}, [][]byte{
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x54, 0x01, 0x00, 0x00,
+ 0x50, 0x03, 0x01, 0x50, 0x77, 0x43, 0x47, 0xfd,
+ 0x1d, 0xb0, 0x60, 0x4c, 0x25, 0x86, 0x45, 0x4a,
+ 0xe5, 0x3f, 0x80, 0x56, 0x18, 0x91, 0x5c, 0xe2,
+ 0x62, 0xc5, 0x77, 0xc2, 0x92, 0xdd, 0xdc, 0x39,
+ 0x23, 0x1d, 0xc5, 0x00, 0x00, 0x28, 0x00, 0x39,
+ 0x00, 0x38, 0x00, 0x35, 0x00, 0x16, 0x00, 0x13,
+ 0x00, 0x0a, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2f,
+ 0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12,
+ 0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08,
+ 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x02, 0x01,
+ 0x00,
},
-
- {
- 0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
- 0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
- 0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
- 0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
- 0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
- 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
- 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
- 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
- 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
- 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
- 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
- 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
- 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
- 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
- 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
- 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
- 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
- 0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
- 0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
- 0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
- 0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
- 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
- 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
- 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
- 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
- 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
- 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
- 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
- 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
- 0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
- 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
- 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
- 0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
- 0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
- 0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
- 0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
- 0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
- 0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
- 0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
- 0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
- 0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
- 0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
- 0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
- 0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
- 0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
- 0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
- 0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
- 0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
- 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
- 0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
- 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
- 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
- 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
- 0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
- 0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
- 0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
- 0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
- 0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
- 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
- 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
- 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
- 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
- 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
- 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
- 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
- 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
- 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
- 0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
- 0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
- 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
- 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
- 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
- 0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
- 0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
- 0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
- 0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
- 0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
- 0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
- 0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
- 0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
- 0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
- 0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
- 0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
- 0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
- 0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
- 0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
- 0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
- 0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
- 0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x08, 0x0d,
- 0x00, 0x00, 0x04, 0x01, 0x01, 0x00, 0x00, 0x16,
- 0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
- },
-
- {
- 0x16, 0x03, 0x01, 0x01, 0xfb, 0x0b, 0x00, 0x01,
- 0xf7, 0x00, 0x01, 0xf4, 0x00, 0x01, 0xf1, 0x30,
- 0x82, 0x01, 0xed, 0x30, 0x82, 0x01, 0x58, 0xa0,
- 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x30,
- 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
- 0x0d, 0x01, 0x01, 0x05, 0x30, 0x26, 0x31, 0x10,
- 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
- 0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f,
- 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
- 0x03, 0x13, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30,
- 0x2e, 0x30, 0x2e, 0x31, 0x30, 0x1e, 0x17, 0x0d,
- 0x31, 0x31, 0x31, 0x32, 0x30, 0x38, 0x30, 0x37,
- 0x35, 0x35, 0x31, 0x32, 0x5a, 0x17, 0x0d, 0x31,
- 0x32, 0x31, 0x32, 0x30, 0x37, 0x30, 0x38, 0x30,
- 0x30, 0x31, 0x32, 0x5a, 0x30, 0x26, 0x31, 0x10,
- 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
- 0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f,
- 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
- 0x03, 0x13, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30,
- 0x2e, 0x30, 0x2e, 0x31, 0x30, 0x81, 0x9c, 0x30,
- 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
- 0x0d, 0x01, 0x01, 0x01, 0x03, 0x81, 0x8c, 0x00,
- 0x30, 0x81, 0x88, 0x02, 0x81, 0x80, 0x4e, 0xd0,
- 0x7b, 0x31, 0xe3, 0x82, 0x64, 0xd9, 0x59, 0xc0,
- 0xc2, 0x87, 0xa4, 0x5e, 0x1e, 0x8b, 0x73, 0x33,
- 0xc7, 0x63, 0x53, 0xdf, 0x66, 0x92, 0x06, 0x84,
- 0xf6, 0x64, 0xd5, 0x8f, 0xe4, 0x36, 0xa7, 0x1d,
- 0x2b, 0xe8, 0xb3, 0x20, 0x36, 0x45, 0x23, 0xb5,
- 0xe3, 0x95, 0xae, 0xed, 0xe0, 0xf5, 0x20, 0x9c,
- 0x8d, 0x95, 0xdf, 0x7f, 0x5a, 0x12, 0xef, 0x87,
- 0xe4, 0x5b, 0x68, 0xe4, 0xe9, 0x0e, 0x74, 0xec,
- 0x04, 0x8a, 0x7f, 0xde, 0x93, 0x27, 0xc4, 0x01,
- 0x19, 0x7a, 0xbd, 0xf2, 0xdc, 0x3d, 0x14, 0xab,
- 0xd0, 0x54, 0xca, 0x21, 0x0c, 0xd0, 0x4d, 0x6e,
- 0x87, 0x2e, 0x5c, 0xc5, 0xd2, 0xbb, 0x4d, 0x4b,
- 0x4f, 0xce, 0xb6, 0x2c, 0xf7, 0x7e, 0x88, 0xec,
- 0x7c, 0xd7, 0x02, 0x91, 0x74, 0xa6, 0x1e, 0x0c,
- 0x1a, 0xda, 0xe3, 0x4a, 0x5a, 0x2e, 0xde, 0x13,
- 0x9c, 0x4c, 0x40, 0x88, 0x59, 0x93, 0x02, 0x03,
- 0x01, 0x00, 0x01, 0xa3, 0x32, 0x30, 0x30, 0x30,
- 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01,
- 0xff, 0x04, 0x04, 0x03, 0x02, 0x00, 0xa0, 0x30,
- 0x0d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x06,
- 0x04, 0x04, 0x01, 0x02, 0x03, 0x04, 0x30, 0x0f,
- 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x08, 0x30,
- 0x06, 0x80, 0x04, 0x01, 0x02, 0x03, 0x04, 0x30,
- 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
- 0x0d, 0x01, 0x01, 0x05, 0x03, 0x81, 0x81, 0x00,
- 0x36, 0x1f, 0xb3, 0x7a, 0x0c, 0x75, 0xc9, 0x6e,
- 0x37, 0x46, 0x61, 0x2b, 0xd5, 0xbd, 0xc0, 0xa7,
- 0x4b, 0xcc, 0x46, 0x9a, 0x81, 0x58, 0x7c, 0x85,
- 0x79, 0x29, 0xc8, 0xc8, 0xc6, 0x67, 0xdd, 0x32,
- 0x56, 0x45, 0x2b, 0x75, 0xb6, 0xe9, 0x24, 0xa9,
- 0x50, 0x9a, 0xbe, 0x1f, 0x5a, 0xfa, 0x1a, 0x15,
- 0xd9, 0xcc, 0x55, 0x95, 0x72, 0x16, 0x83, 0xb9,
- 0xc2, 0xb6, 0x8f, 0xfd, 0x88, 0x8c, 0x38, 0x84,
- 0x1d, 0xab, 0x5d, 0x92, 0x31, 0x13, 0x4f, 0xfd,
- 0x83, 0x3b, 0xc6, 0x9d, 0xf1, 0x11, 0x62, 0xb6,
- 0x8b, 0xec, 0xab, 0x67, 0xbe, 0xc8, 0x64, 0xb0,
- 0x11, 0x50, 0x46, 0x58, 0x17, 0x6b, 0x99, 0x1c,
- 0xd3, 0x1d, 0xfc, 0x06, 0xf1, 0x0e, 0xe5, 0x96,
- 0xa8, 0x0c, 0xf9, 0x78, 0x20, 0xb7, 0x44, 0x18,
- 0x51, 0x8d, 0x10, 0x7e, 0x4f, 0x94, 0x67, 0xdf,
- 0xa3, 0x4e, 0x70, 0x73, 0x8e, 0x90, 0x91, 0x85,
- 0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
- 0x82, 0x00, 0x80, 0xa7, 0x2f, 0xed, 0xfa, 0xc2,
- 0xbd, 0x46, 0xa1, 0xf2, 0x69, 0xc5, 0x1d, 0xa1,
- 0x34, 0xd6, 0xd0, 0x84, 0xf5, 0x5d, 0x8c, 0x82,
- 0x8d, 0x98, 0x82, 0x9c, 0xd9, 0x07, 0xe0, 0xf7,
- 0x55, 0x49, 0x4d, 0xa1, 0x48, 0x59, 0x02, 0xd3,
- 0x84, 0x37, 0xaf, 0x01, 0xb3, 0x3a, 0xf4, 0xed,
- 0x99, 0xbe, 0x67, 0x36, 0x19, 0x55, 0xf3, 0xf9,
- 0xcb, 0x94, 0xe5, 0x7b, 0x8b, 0x77, 0xf2, 0x5f,
- 0x4c, 0xfe, 0x01, 0x1f, 0x7b, 0xd7, 0x23, 0x49,
- 0x0c, 0xcb, 0x6c, 0xb0, 0xe7, 0x77, 0xd6, 0xcf,
- 0xa8, 0x7d, 0xdb, 0xa7, 0x14, 0xe2, 0xf5, 0xf3,
- 0xff, 0xba, 0x23, 0xd2, 0x9a, 0x36, 0x14, 0x60,
- 0x2a, 0x91, 0x5d, 0x2b, 0x35, 0x3b, 0xb6, 0xdd,
- 0xcb, 0x6b, 0xdc, 0x18, 0xdc, 0x33, 0xb8, 0xb3,
- 0xc7, 0x27, 0x7e, 0xfc, 0xd2, 0xf7, 0x97, 0x90,
- 0x5e, 0x17, 0xac, 0x14, 0x8e, 0x0f, 0xca, 0xb5,
- 0x6f, 0xc9, 0x2d, 0x16, 0x03, 0x01, 0x00, 0x86,
- 0x0f, 0x00, 0x00, 0x82, 0x00, 0x80, 0x44, 0x7f,
- 0xa2, 0x59, 0x60, 0x0b, 0x5a, 0xc4, 0xaf, 0x1e,
- 0x60, 0xa5, 0x24, 0xea, 0xc1, 0xc3, 0x22, 0x21,
- 0x6b, 0x22, 0x8b, 0x2a, 0x11, 0x82, 0x68, 0x7d,
- 0xb9, 0xdd, 0x9c, 0x27, 0x4c, 0xc2, 0xc8, 0xa2,
- 0x8b, 0x6b, 0x77, 0x8d, 0x3a, 0x2b, 0x8d, 0x2f,
- 0x6a, 0x2b, 0x43, 0xd2, 0xd1, 0xc6, 0x41, 0x79,
- 0xa2, 0x4f, 0x2b, 0xc2, 0xf7, 0xb2, 0x10, 0xad,
- 0xa6, 0x01, 0x51, 0x51, 0x25, 0xe7, 0x58, 0x7a,
- 0xcf, 0x3b, 0xc4, 0x29, 0xb5, 0xe5, 0xa7, 0x83,
- 0xe6, 0xcb, 0x1e, 0xf3, 0x02, 0x0f, 0x53, 0x3b,
- 0xb5, 0x39, 0xef, 0x9c, 0x42, 0xe0, 0xa6, 0x9b,
- 0x2b, 0xdd, 0x60, 0xae, 0x0a, 0x73, 0x35, 0xbe,
- 0x26, 0x10, 0x1b, 0xe9, 0xe9, 0x61, 0xab, 0x20,
- 0xa5, 0x48, 0xc6, 0x60, 0xa6, 0x50, 0x3c, 0xfb,
- 0xa7, 0xca, 0xb0, 0x80, 0x95, 0x1e, 0xce, 0xc7,
- 0xbb, 0x68, 0x44, 0xdc, 0x0e, 0x0e, 0x14, 0x03,
- 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01, 0x00,
- 0x24, 0xb6, 0xcd, 0x0c, 0x78, 0xfd, 0xd6, 0xff,
- 0xbe, 0x97, 0xd5, 0x0a, 0x7d, 0x4f, 0xa1, 0x03,
- 0x78, 0xc8, 0x61, 0x6f, 0xf2, 0x4b, 0xa8, 0x56,
- 0x4f, 0x3c, 0xa2, 0xd9, 0xd0, 0x20, 0x13, 0x1b,
- 0x8b, 0x36, 0xb7, 0x33, 0x9c,
- },
-
- {
- 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
- 0x01, 0x00, 0x24, 0xa3, 0x43, 0x94, 0xe7, 0xdf,
- 0xb6, 0xc3, 0x03, 0x9f, 0xc1, 0x59, 0x0c, 0xc3,
- 0x13, 0xae, 0xed, 0xcf, 0xff, 0xf1, 0x80, 0xf3,
- 0x13, 0x63, 0x1c, 0xf0, 0xca, 0xad, 0x9e, 0x71,
- 0x46, 0x5f, 0x6b, 0xeb, 0x10, 0x3f, 0xe3, 0x17,
- 0x03, 0x01, 0x00, 0x21, 0xe9, 0x80, 0x95, 0x6e,
- 0x05, 0x55, 0x2f, 0xed, 0x4d, 0xde, 0x17, 0x3a,
- 0x32, 0x9b, 0x2a, 0x74, 0x30, 0x4f, 0xe0, 0x9f,
- 0x4e, 0xd3, 0x06, 0xbd, 0x3a, 0x43, 0x75, 0x8b,
- 0x5b, 0x9a, 0xd8, 0x2e, 0x56, 0x15, 0x03, 0x01,
- 0x00, 0x16, 0x53, 0xf5, 0xff, 0xe0, 0xa1, 0x6c,
- 0x33, 0xf4, 0x4e, 0x89, 0x68, 0xe1, 0xf7, 0x61,
- 0x13, 0xb3, 0x12, 0xa1, 0x8e, 0x5a, 0x7a, 0x02,
- },
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
+ 0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
+ 0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
+ 0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
+ 0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
+ 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+ 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+ 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+ 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+ 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
+ 0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
+ 0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
+ 0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
+ 0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
+ 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
+ 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
+ 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+ 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
+ 0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+ 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
+ 0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
+ 0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
+ 0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
+ 0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
+ 0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
+ 0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
+ 0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
+ 0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
+ 0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
+ 0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
+ 0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
+ 0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
+ 0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
+ 0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
+ 0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
+ 0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
+ 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
+ 0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
+ 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
+ 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
+ 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
+ 0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
+ 0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
+ 0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
+ 0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
+ 0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
+ 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
+ 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
+ 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
+ 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
+ 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
+ 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
+ 0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
+ 0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+ 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
+ 0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
+ 0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
+ 0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
+ 0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
+ 0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
+ 0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
+ 0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
+ 0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
+ 0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
+ 0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
+ 0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
+ 0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
+ 0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
+ 0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
+ 0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
+ 0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
+ 0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x08, 0x0d,
+ 0x00, 0x00, 0x04, 0x01, 0x01, 0x00, 0x00, 0x16,
+ 0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
},
- },
+ {
+ 0x16, 0x03, 0x01, 0x01, 0xfb, 0x0b, 0x00, 0x01,
+ 0xf7, 0x00, 0x01, 0xf4, 0x00, 0x01, 0xf1, 0x30,
+ 0x82, 0x01, 0xed, 0x30, 0x82, 0x01, 0x58, 0xa0,
+ 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x30,
+ 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x30, 0x26, 0x31, 0x10,
+ 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+ 0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f,
+ 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x13, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30,
+ 0x2e, 0x30, 0x2e, 0x31, 0x30, 0x1e, 0x17, 0x0d,
+ 0x31, 0x31, 0x31, 0x32, 0x30, 0x38, 0x30, 0x37,
+ 0x35, 0x35, 0x31, 0x32, 0x5a, 0x17, 0x0d, 0x31,
+ 0x32, 0x31, 0x32, 0x30, 0x37, 0x30, 0x38, 0x30,
+ 0x30, 0x31, 0x32, 0x5a, 0x30, 0x26, 0x31, 0x10,
+ 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+ 0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f,
+ 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x13, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30,
+ 0x2e, 0x30, 0x2e, 0x31, 0x30, 0x81, 0x9c, 0x30,
+ 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x01, 0x03, 0x81, 0x8c, 0x00,
+ 0x30, 0x81, 0x88, 0x02, 0x81, 0x80, 0x4e, 0xd0,
+ 0x7b, 0x31, 0xe3, 0x82, 0x64, 0xd9, 0x59, 0xc0,
+ 0xc2, 0x87, 0xa4, 0x5e, 0x1e, 0x8b, 0x73, 0x33,
+ 0xc7, 0x63, 0x53, 0xdf, 0x66, 0x92, 0x06, 0x84,
+ 0xf6, 0x64, 0xd5, 0x8f, 0xe4, 0x36, 0xa7, 0x1d,
+ 0x2b, 0xe8, 0xb3, 0x20, 0x36, 0x45, 0x23, 0xb5,
+ 0xe3, 0x95, 0xae, 0xed, 0xe0, 0xf5, 0x20, 0x9c,
+ 0x8d, 0x95, 0xdf, 0x7f, 0x5a, 0x12, 0xef, 0x87,
+ 0xe4, 0x5b, 0x68, 0xe4, 0xe9, 0x0e, 0x74, 0xec,
+ 0x04, 0x8a, 0x7f, 0xde, 0x93, 0x27, 0xc4, 0x01,
+ 0x19, 0x7a, 0xbd, 0xf2, 0xdc, 0x3d, 0x14, 0xab,
+ 0xd0, 0x54, 0xca, 0x21, 0x0c, 0xd0, 0x4d, 0x6e,
+ 0x87, 0x2e, 0x5c, 0xc5, 0xd2, 0xbb, 0x4d, 0x4b,
+ 0x4f, 0xce, 0xb6, 0x2c, 0xf7, 0x7e, 0x88, 0xec,
+ 0x7c, 0xd7, 0x02, 0x91, 0x74, 0xa6, 0x1e, 0x0c,
+ 0x1a, 0xda, 0xe3, 0x4a, 0x5a, 0x2e, 0xde, 0x13,
+ 0x9c, 0x4c, 0x40, 0x88, 0x59, 0x93, 0x02, 0x03,
+ 0x01, 0x00, 0x01, 0xa3, 0x32, 0x30, 0x30, 0x30,
+ 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01,
+ 0xff, 0x04, 0x04, 0x03, 0x02, 0x00, 0xa0, 0x30,
+ 0x0d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x06,
+ 0x04, 0x04, 0x01, 0x02, 0x03, 0x04, 0x30, 0x0f,
+ 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x08, 0x30,
+ 0x06, 0x80, 0x04, 0x01, 0x02, 0x03, 0x04, 0x30,
+ 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x03, 0x81, 0x81, 0x00,
+ 0x36, 0x1f, 0xb3, 0x7a, 0x0c, 0x75, 0xc9, 0x6e,
+ 0x37, 0x46, 0x61, 0x2b, 0xd5, 0xbd, 0xc0, 0xa7,
+ 0x4b, 0xcc, 0x46, 0x9a, 0x81, 0x58, 0x7c, 0x85,
+ 0x79, 0x29, 0xc8, 0xc8, 0xc6, 0x67, 0xdd, 0x32,
+ 0x56, 0x45, 0x2b, 0x75, 0xb6, 0xe9, 0x24, 0xa9,
+ 0x50, 0x9a, 0xbe, 0x1f, 0x5a, 0xfa, 0x1a, 0x15,
+ 0xd9, 0xcc, 0x55, 0x95, 0x72, 0x16, 0x83, 0xb9,
+ 0xc2, 0xb6, 0x8f, 0xfd, 0x88, 0x8c, 0x38, 0x84,
+ 0x1d, 0xab, 0x5d, 0x92, 0x31, 0x13, 0x4f, 0xfd,
+ 0x83, 0x3b, 0xc6, 0x9d, 0xf1, 0x11, 0x62, 0xb6,
+ 0x8b, 0xec, 0xab, 0x67, 0xbe, 0xc8, 0x64, 0xb0,
+ 0x11, 0x50, 0x46, 0x58, 0x17, 0x6b, 0x99, 0x1c,
+ 0xd3, 0x1d, 0xfc, 0x06, 0xf1, 0x0e, 0xe5, 0x96,
+ 0xa8, 0x0c, 0xf9, 0x78, 0x20, 0xb7, 0x44, 0x18,
+ 0x51, 0x8d, 0x10, 0x7e, 0x4f, 0x94, 0x67, 0xdf,
+ 0xa3, 0x4e, 0x70, 0x73, 0x8e, 0x90, 0x91, 0x85,
+ 0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
+ 0x82, 0x00, 0x80, 0x81, 0x46, 0x43, 0xf9, 0xe7,
+ 0xda, 0x8c, 0x92, 0x3a, 0x78, 0x1a, 0x86, 0xb3,
+ 0xbe, 0x83, 0x22, 0xb6, 0xaa, 0x57, 0x37, 0x68,
+ 0x9e, 0x54, 0x3f, 0xd3, 0xce, 0x4d, 0x5e, 0x2a,
+ 0xdc, 0xb0, 0x49, 0x02, 0xbb, 0xc0, 0x45, 0x58,
+ 0x79, 0x10, 0xc7, 0x94, 0x60, 0x9f, 0x1b, 0x5f,
+ 0x18, 0x31, 0x37, 0x9c, 0xe0, 0xe6, 0xdf, 0x5e,
+ 0x70, 0x44, 0xf6, 0x8b, 0xdf, 0xf1, 0xf6, 0x43,
+ 0xc8, 0x2f, 0xd1, 0xce, 0xd0, 0xd6, 0x64, 0x4f,
+ 0xe8, 0x2b, 0xfa, 0xd3, 0xd0, 0xd1, 0x2e, 0xaa,
+ 0x9b, 0x1d, 0x13, 0x5c, 0xbe, 0x57, 0x41, 0x6c,
+ 0x5e, 0x8d, 0xea, 0xa9, 0x3c, 0x58, 0xa0, 0x30,
+ 0x92, 0x77, 0x7a, 0xed, 0x64, 0x58, 0xe5, 0x7f,
+ 0x6a, 0x93, 0x89, 0x66, 0x3d, 0x13, 0x16, 0x56,
+ 0xa0, 0xad, 0xdc, 0x68, 0x95, 0x87, 0x81, 0xd0,
+ 0x90, 0x4d, 0x5f, 0xfe, 0x3e, 0x83, 0x15, 0x2e,
+ 0x50, 0x3c, 0xdd, 0x16, 0x03, 0x01, 0x00, 0x86,
+ 0x0f, 0x00, 0x00, 0x82, 0x00, 0x80, 0x2b, 0xf8,
+ 0x56, 0x48, 0xbb, 0x02, 0x37, 0x15, 0x02, 0x74,
+ 0x33, 0x53, 0x65, 0xa7, 0x7c, 0x2f, 0xc6, 0x5d,
+ 0x80, 0x59, 0xc1, 0xc2, 0x3b, 0xa9, 0xde, 0x4e,
+ 0x70, 0x51, 0xd2, 0xde, 0x58, 0x7f, 0xd8, 0xb9,
+ 0xb6, 0x3b, 0xc8, 0xaa, 0xfc, 0x3d, 0x53, 0x2d,
+ 0x61, 0x4d, 0xf5, 0x60, 0x12, 0xc2, 0xa5, 0x39,
+ 0x0c, 0xa7, 0xc6, 0xac, 0x26, 0x4b, 0xf4, 0x5f,
+ 0xe9, 0xf4, 0xf2, 0x73, 0x48, 0xe4, 0x3b, 0xee,
+ 0xf2, 0xee, 0xc0, 0xee, 0xfb, 0x5b, 0x60, 0xc2,
+ 0x74, 0xe6, 0xf6, 0x43, 0x3e, 0xa4, 0xf7, 0x97,
+ 0x3d, 0xfc, 0xe9, 0x44, 0x21, 0x18, 0x46, 0x05,
+ 0x33, 0xf8, 0xfe, 0x35, 0x5b, 0xe6, 0x8f, 0xef,
+ 0x4d, 0x4c, 0x87, 0xf6, 0xb4, 0x6e, 0x6b, 0x39,
+ 0xd8, 0xaa, 0x1b, 0x33, 0xc9, 0x1c, 0x66, 0x48,
+ 0xbe, 0xfa, 0xb5, 0x92, 0x09, 0xfd, 0xb9, 0xb9,
+ 0xca, 0xe6, 0x6d, 0x71, 0xc6, 0x89, 0x14, 0x03,
+ 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01, 0x00,
+ 0x24, 0xe3, 0x2b, 0xef, 0x17, 0xd5, 0xa6, 0x4c,
+ 0x2e, 0x10, 0xac, 0x9c, 0xfe, 0x0f, 0x18, 0x43,
+ 0x95, 0x00, 0x81, 0xf7, 0x7c, 0x00, 0x5b, 0x89,
+ 0x52, 0x41, 0xe4, 0x8a, 0x8a, 0x34, 0x31, 0x09,
+ 0x48, 0x7c, 0xc5, 0xc3, 0x83,
+ },
+ {
+ 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+ 0x01, 0x00, 0x24, 0x24, 0xaa, 0xaa, 0x56, 0x8b,
+ 0x41, 0x87, 0x01, 0xbe, 0x80, 0x05, 0x51, 0x36,
+ 0x08, 0xfc, 0xaf, 0xff, 0x7f, 0xf4, 0x74, 0x84,
+ 0x88, 0xdc, 0xb8, 0x8e, 0x70, 0x6c, 0x22, 0x04,
+ 0xee, 0x45, 0x8d, 0xda, 0xed, 0xc6, 0x05, 0x17,
+ 0x03, 0x01, 0x00, 0x21, 0x91, 0x49, 0x4b, 0xed,
+ 0xa3, 0x41, 0xe9, 0x88, 0x3b, 0xa3, 0x01, 0xee,
+ 0x77, 0x4e, 0x12, 0xb4, 0xcd, 0x5e, 0xcc, 0x45,
+ 0x02, 0x5a, 0x20, 0xd6, 0xe8, 0xac, 0xcb, 0x60,
+ 0xcb, 0x1b, 0xef, 0xf9, 0xc2, 0x15, 0x03, 0x01,
+ 0x00, 0x16, 0xd4, 0xcd, 0x92, 0x3c, 0x10, 0x93,
+ 0x68, 0xc3, 0xdd, 0xaf, 0xe9, 0xcb, 0x5d, 0x94,
+ 0x1a, 0x06, 0x81, 0xa7, 0x78, 0x0f, 0xc3, 0x03,
+ },
+ }},
}
// cert.pem and key.pem were generated with generate_cert.go
@@ -1703,7 +1984,7 @@ GFGNEH5PlGffo05wc46QkYU=
/* corresponding key.pem for cert.pem is:
-----BEGIN RSA PRIVATE KEY-----
-MIICXAIBAAKBgE7QezHjgmTZWcDCh6ReHotzM8djU99mkgaE9mTVj+Q2px0r6LMg
+MIICWgIBAAKBgE7QezHjgmTZWcDCh6ReHotzM8djU99mkgaE9mTVj+Q2px0r6LMg
NkUjteOVru3g9SCcjZXff1oS74fkW2jk6Q507ASKf96TJ8QBGXq98tw9FKvQVMoh
DNBNbocuXMXSu01LT862LPd+iOx81wKRdKYeDBra40paLt4TnExAiFmTAgMBAAEC
gYBxvXd8yNteFTns8A/2yomEMC4yeosJJSpp1CsN3BJ7g8/qTnrVPxBy+RU+qr63
@@ -1715,6 +1996,6 @@ RkKVpenBHyrGg0oeN5La7URILWKj7CPXAkBKo6F+d+phNjwIFoN1Xb/RA32w/D1I
saG9sF+UEhRt9AxUfW/U/tIQ9V0ZHHcSg1XaCM5Nvp934brdKdvTOKnJAkBD5h/3
Rybatlvg/fzBEaJFyq09zhngkxlZOUtBVTqzl17RVvY2orgH02U4HbCHy4phxOn7
qTdQRYlHRftgnWK1AkANibn9PRYJ7mJyJ9Dyj2QeNcSkSTzrt0tPvUMf4+meJymN
-1Ntu5+S1DLLzfxlaljWG6ylW6DNxujCyuXIV2rvAMAA=
+1Ntu5+S1DLLzfxlaljWG6ylW6DNxujCyuXIV2rvA
-----END RSA PRIVATE KEY-----
*/
diff --git a/src/pkg/crypto/tls/parse-gnutls-cli-debug-log.py b/src/pkg/crypto/tls/parse-gnutls-cli-debug-log.py
deleted file mode 100644
index 5692bd32f..000000000
--- a/src/pkg/crypto/tls/parse-gnutls-cli-debug-log.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# 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.
-
-# This code is used to parse the debug log from gnutls-cli and generate a
-# script of the handshake. This script is included in handshake_server_test.go.
-# See the comments there for details.
-
-import sys
-
-blocks = []
-
-READ = 1
-WRITE = 2
-
-currentBlockType = 0
-currentBlock = []
-for line in sys.stdin.readlines():
- line = line[:-1]
- if line.startswith("|<7>| WRITE: "):
- if currentBlockType != WRITE:
- if len(currentBlock) > 0:
- blocks.append(currentBlock)
- currentBlock = []
- currentBlockType = WRITE
- elif line.startswith("|<7>| READ: "):
- if currentBlockType != READ:
- if len(currentBlock) > 0:
- blocks.append(currentBlock)
- currentBlock = []
- currentBlockType = READ
- elif line.startswith("|<7>| 0"):
- line = line[13:]
- line = line.strip()
- bs = line.split()
- for b in bs:
- currentBlock.append(int(b, 16))
- elif line.startswith("|<7>| RB-PEEK: Read 1 bytes"):
- currentBlock = currentBlock[:-1]
-
-if len(currentBlock) > 0:
- blocks.append(currentBlock)
-
-for block in blocks:
- sys.stdout.write("\t{\n")
-
- i = 0
- for b in block:
- if i % 8 == 0:
- sys.stdout.write("\t\t")
- sys.stdout.write("0x%02x," % b)
- if i % 8 == 7:
- sys.stdout.write("\n")
- else:
- sys.stdout.write(" ")
- i += 1
- sys.stdout.write("\n\t},\n\n")
diff --git a/src/pkg/crypto/tls/prf.go b/src/pkg/crypto/tls/prf.go
index 637ef03e2..df1eaad05 100644
--- a/src/pkg/crypto/tls/prf.go
+++ b/src/pkg/crypto/tls/prf.go
@@ -106,10 +106,9 @@ var keyExpansionLabel = []byte("key expansion")
var clientFinishedLabel = []byte("client finished")
var serverFinishedLabel = []byte("server finished")
-// keysFromPreMasterSecret generates the connection keys from the pre master
-// secret, given the lengths of the MAC key, cipher key and IV, as defined in
-// RFC 2246, section 6.3.
-func keysFromPreMasterSecret(version uint16, preMasterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
+// masterFromPreMasterSecret generates the master secret from the pre-master
+// secret. See http://tools.ietf.org/html/rfc5246#section-8.1
+func masterFromPreMasterSecret(version uint16, preMasterSecret, clientRandom, serverRandom []byte) []byte {
prf := pRF10
if version == versionSSL30 {
prf = pRF30
@@ -118,9 +117,21 @@ func keysFromPreMasterSecret(version uint16, preMasterSecret, clientRandom, serv
var seed [tlsRandomLength * 2]byte
copy(seed[0:len(clientRandom)], clientRandom)
copy(seed[len(clientRandom):], serverRandom)
- masterSecret = make([]byte, masterSecretLength)
+ masterSecret := make([]byte, masterSecretLength)
prf(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
+ return masterSecret
+}
+// keysFromMasterSecret generates the connection keys from the master
+// secret, given the lengths of the MAC key, cipher key and IV, as defined in
+// RFC 2246, section 6.3.
+func keysFromMasterSecret(version uint16, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
+ prf := pRF10
+ if version == versionSSL30 {
+ prf = pRF30
+ }
+
+ var seed [tlsRandomLength * 2]byte
copy(seed[0:len(clientRandom)], serverRandom)
copy(seed[len(serverRandom):], clientRandom)
diff --git a/src/pkg/crypto/tls/prf_test.go b/src/pkg/crypto/tls/prf_test.go
index a32392cef..773a2b2ff 100644
--- a/src/pkg/crypto/tls/prf_test.go
+++ b/src/pkg/crypto/tls/prf_test.go
@@ -48,18 +48,23 @@ func TestKeysFromPreMasterSecret(t *testing.T) {
in, _ := hex.DecodeString(test.preMasterSecret)
clientRandom, _ := hex.DecodeString(test.clientRandom)
serverRandom, _ := hex.DecodeString(test.serverRandom)
- master, clientMAC, serverMAC, clientKey, serverKey, _, _ := keysFromPreMasterSecret(test.version, in, clientRandom, serverRandom, test.macLen, test.keyLen, 0)
- masterString := hex.EncodeToString(master)
+
+ masterSecret := masterFromPreMasterSecret(test.version, in, clientRandom, serverRandom)
+ if s := hex.EncodeToString(masterSecret); s != test.masterSecret {
+ t.Errorf("#%d: bad master secret %s, want %s", i, s, test.masterSecret)
+ continue
+ }
+
+ clientMAC, serverMAC, clientKey, serverKey, _, _ := keysFromMasterSecret(test.version, masterSecret, clientRandom, serverRandom, test.macLen, test.keyLen, 0)
clientMACString := hex.EncodeToString(clientMAC)
serverMACString := hex.EncodeToString(serverMAC)
clientKeyString := hex.EncodeToString(clientKey)
serverKeyString := hex.EncodeToString(serverKey)
- if masterString != test.masterSecret ||
- clientMACString != test.clientMAC ||
+ if clientMACString != test.clientMAC ||
serverMACString != test.serverMAC ||
clientKeyString != test.clientKey ||
serverKeyString != test.serverKey {
- t.Errorf("#%d: got: (%s, %s, %s, %s, %s) want: (%s, %s, %s, %s, %s)", i, masterString, clientMACString, serverMACString, clientKeyString, serverKeyString, test.masterSecret, test.clientMAC, test.serverMAC, test.clientKey, test.serverKey)
+ t.Errorf("#%d: got: (%s, %s, %s, %s) want: (%s, %s, %s, %s)", i, clientMACString, serverMACString, clientKeyString, serverKeyString, test.clientMAC, test.serverMAC, test.clientKey, test.serverKey)
}
}
}
diff --git a/src/pkg/crypto/tls/root_test.go b/src/pkg/crypto/tls/root_test.go
deleted file mode 100644
index e61c21851..000000000
--- a/src/pkg/crypto/tls/root_test.go
+++ /dev/null
@@ -1,61 +0,0 @@
-// 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.
-
-package tls
-
-import (
- "crypto/x509"
- "runtime"
- "testing"
-)
-
-var tlsServers = []string{
- "google.com",
- "github.com",
- "twitter.com",
-}
-
-func TestOSCertBundles(t *testing.T) {
- if testing.Short() {
- t.Logf("skipping certificate tests in short mode")
- return
- }
-
- for _, addr := range tlsServers {
- conn, err := Dial("tcp", addr+":443", &Config{ServerName: addr})
- if err != nil {
- t.Errorf("unable to verify %v: %v", addr, err)
- continue
- }
- err = conn.Close()
- if err != nil {
- t.Error(err)
- }
- }
-}
-
-func TestCertHostnameVerifyWindows(t *testing.T) {
- if runtime.GOOS != "windows" {
- return
- }
-
- if testing.Short() {
- t.Logf("skipping certificate tests in short mode")
- return
- }
-
- for _, addr := range tlsServers {
- cfg := &Config{ServerName: "example.com"}
- conn, err := Dial("tcp", addr+":443", cfg)
- if err == nil {
- conn.Close()
- t.Errorf("should fail to verify for example.com: %v", addr)
- continue
- }
- _, ok := err.(x509.HostnameError)
- if !ok {
- t.Errorf("error type mismatch, got: %v", err)
- }
- }
-}
diff --git a/src/pkg/crypto/tls/ticket.go b/src/pkg/crypto/tls/ticket.go
new file mode 100644
index 000000000..4cfc5a53f
--- /dev/null
+++ b/src/pkg/crypto/tls/ticket.go
@@ -0,0 +1,182 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tls
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/hmac"
+ "crypto/sha256"
+ "crypto/subtle"
+ "errors"
+ "io"
+)
+
+// sessionState contains the information that is serialized into a session
+// ticket in order to later resume a connection.
+type sessionState struct {
+ vers uint16
+ cipherSuite uint16
+ masterSecret []byte
+ certificates [][]byte
+}
+
+func (s *sessionState) equal(i interface{}) bool {
+ s1, ok := i.(*sessionState)
+ if !ok {
+ return false
+ }
+
+ if s.vers != s1.vers ||
+ s.cipherSuite != s1.cipherSuite ||
+ !bytes.Equal(s.masterSecret, s1.masterSecret) {
+ return false
+ }
+
+ if len(s.certificates) != len(s1.certificates) {
+ return false
+ }
+
+ for i := range s.certificates {
+ if !bytes.Equal(s.certificates[i], s1.certificates[i]) {
+ return false
+ }
+ }
+
+ return true
+}
+
+func (s *sessionState) marshal() []byte {
+ length := 2 + 2 + 2 + len(s.masterSecret) + 2
+ for _, cert := range s.certificates {
+ length += 4 + len(cert)
+ }
+
+ ret := make([]byte, length)
+ x := ret
+ x[0] = byte(s.vers >> 8)
+ x[1] = byte(s.vers)
+ x[2] = byte(s.cipherSuite >> 8)
+ x[3] = byte(s.cipherSuite)
+ x[4] = byte(len(s.masterSecret) >> 8)
+ x[5] = byte(len(s.masterSecret))
+ x = x[6:]
+ copy(x, s.masterSecret)
+ x = x[len(s.masterSecret):]
+
+ x[0] = byte(len(s.certificates) >> 8)
+ x[1] = byte(len(s.certificates))
+ x = x[2:]
+
+ for _, cert := range s.certificates {
+ x[0] = byte(len(cert) >> 24)
+ x[1] = byte(len(cert) >> 16)
+ x[2] = byte(len(cert) >> 8)
+ x[3] = byte(len(cert))
+ copy(x[4:], cert)
+ x = x[4+len(cert):]
+ }
+
+ return ret
+}
+
+func (s *sessionState) unmarshal(data []byte) bool {
+ if len(data) < 8 {
+ return false
+ }
+
+ s.vers = uint16(data[0])<<8 | uint16(data[1])
+ s.cipherSuite = uint16(data[2])<<8 | uint16(data[3])
+ masterSecretLen := int(data[4])<<8 | int(data[5])
+ data = data[6:]
+ if len(data) < masterSecretLen {
+ return false
+ }
+
+ s.masterSecret = data[:masterSecretLen]
+ data = data[masterSecretLen:]
+
+ if len(data) < 2 {
+ return false
+ }
+
+ numCerts := int(data[0])<<8 | int(data[1])
+ data = data[2:]
+
+ s.certificates = make([][]byte, numCerts)
+ for i := range s.certificates {
+ if len(data) < 4 {
+ return false
+ }
+ certLen := int(data[0])<<24 | int(data[1])<<16 | int(data[2])<<8 | int(data[3])
+ data = data[4:]
+ if certLen < 0 {
+ return false
+ }
+ if len(data) < certLen {
+ return false
+ }
+ s.certificates[i] = data[:certLen]
+ data = data[certLen:]
+ }
+
+ if len(data) > 0 {
+ return false
+ }
+
+ return true
+}
+
+func (c *Conn) encryptTicket(state *sessionState) ([]byte, error) {
+ serialized := state.marshal()
+ encrypted := make([]byte, aes.BlockSize+len(serialized)+sha256.Size)
+ iv := encrypted[:aes.BlockSize]
+ macBytes := encrypted[len(encrypted)-sha256.Size:]
+
+ if _, err := io.ReadFull(c.config.rand(), iv); err != nil {
+ return nil, err
+ }
+ block, err := aes.NewCipher(c.config.SessionTicketKey[:16])
+ if err != nil {
+ return nil, errors.New("tls: failed to create cipher while encrypting ticket: " + err.Error())
+ }
+ cipher.NewCTR(block, iv).XORKeyStream(encrypted[aes.BlockSize:], serialized)
+
+ mac := hmac.New(sha256.New, c.config.SessionTicketKey[16:32])
+ mac.Write(encrypted[:len(encrypted)-sha256.Size])
+ mac.Sum(macBytes[:0])
+
+ return encrypted, nil
+}
+
+func (c *Conn) decryptTicket(encrypted []byte) (*sessionState, bool) {
+ if len(encrypted) < aes.BlockSize+sha256.Size {
+ return nil, false
+ }
+
+ iv := encrypted[:aes.BlockSize]
+ macBytes := encrypted[len(encrypted)-sha256.Size:]
+
+ mac := hmac.New(sha256.New, c.config.SessionTicketKey[16:32])
+ mac.Write(encrypted[:len(encrypted)-sha256.Size])
+ expected := mac.Sum(nil)
+
+ if subtle.ConstantTimeCompare(macBytes, expected) != 1 {
+ return nil, false
+ }
+
+ block, err := aes.NewCipher(c.config.SessionTicketKey[:16])
+ if err != nil {
+ return nil, false
+ }
+ ciphertext := encrypted[aes.BlockSize : len(encrypted)-sha256.Size]
+ plaintext := ciphertext
+ cipher.NewCTR(block, iv).XORKeyStream(plaintext, ciphertext)
+
+ state := new(sessionState)
+ ok := state.unmarshal(plaintext)
+ return state, ok
+}
diff --git a/src/pkg/crypto/tls/tls.go b/src/pkg/crypto/tls/tls.go
index 09df5ad44..9230656d6 100644
--- a/src/pkg/crypto/tls/tls.go
+++ b/src/pkg/crypto/tls/tls.go
@@ -6,6 +6,8 @@
package tls
import (
+ "crypto"
+ "crypto/ecdsa"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
@@ -146,30 +148,22 @@ func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (cert Certificate, err error)
return
}
- keyDERBlock, _ := pem.Decode(keyPEMBlock)
- if keyDERBlock == nil {
- err = errors.New("crypto/tls: failed to parse key PEM data")
- return
- }
-
- // OpenSSL 0.9.8 generates PKCS#1 private keys by default, while
- // OpenSSL 1.0.0 generates PKCS#8 keys. We try both.
- var key *rsa.PrivateKey
- if key, err = x509.ParsePKCS1PrivateKey(keyDERBlock.Bytes); err != nil {
- var privKey interface{}
- if privKey, err = x509.ParsePKCS8PrivateKey(keyDERBlock.Bytes); err != nil {
- err = errors.New("crypto/tls: failed to parse key: " + err.Error())
+ var keyDERBlock *pem.Block
+ for {
+ keyDERBlock, keyPEMBlock = pem.Decode(keyPEMBlock)
+ if keyDERBlock == nil {
+ err = errors.New("crypto/tls: failed to parse key PEM data")
return
}
-
- var ok bool
- if key, ok = privKey.(*rsa.PrivateKey); !ok {
- err = errors.New("crypto/tls: found non-RSA private key in PKCS#8 wrapping")
- return
+ if keyDERBlock.Type == "PRIVATE KEY" || strings.HasSuffix(keyDERBlock.Type, " PRIVATE KEY") {
+ break
}
}
- cert.PrivateKey = key
+ cert.PrivateKey, err = parsePrivateKey(keyDERBlock.Bytes)
+ if err != nil {
+ return
+ }
// We don't need to parse the public key for TLS, but we so do anyway
// to check that it looks sane and matches the private key.
@@ -178,10 +172,54 @@ func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (cert Certificate, err error)
return
}
- if x509Cert.PublicKeyAlgorithm != x509.RSA || x509Cert.PublicKey.(*rsa.PublicKey).N.Cmp(key.PublicKey.N) != 0 {
- err = errors.New("crypto/tls: private key does not match public key")
+ switch pub := x509Cert.PublicKey.(type) {
+ case *rsa.PublicKey:
+ priv, ok := cert.PrivateKey.(*rsa.PrivateKey)
+ if !ok {
+ err = errors.New("crypto/tls: private key type does not match public key type")
+ return
+ }
+ if pub.N.Cmp(priv.N) != 0 {
+ err = errors.New("crypto/tls: private key does not match public key")
+ return
+ }
+ case *ecdsa.PublicKey:
+ priv, ok := cert.PrivateKey.(*ecdsa.PrivateKey)
+ if !ok {
+ err = errors.New("crypto/tls: private key type does not match public key type")
+ return
+
+ }
+ if pub.X.Cmp(priv.X) != 0 || pub.Y.Cmp(priv.Y) != 0 {
+ err = errors.New("crypto/tls: private key does not match public key")
+ return
+ }
+ default:
+ err = errors.New("crypto/tls: unknown public key algorithm")
return
}
return
}
+
+// Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates
+// PKCS#1 private keys by default, while OpenSSL 1.0.0 generates PKCS#8 keys.
+// OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three.
+func parsePrivateKey(der []byte) (crypto.PrivateKey, error) {
+ if key, err := x509.ParsePKCS1PrivateKey(der); err == nil {
+ return key, nil
+ }
+ if key, err := x509.ParsePKCS8PrivateKey(der); err == nil {
+ switch key := key.(type) {
+ case *rsa.PrivateKey, *ecdsa.PrivateKey:
+ return key, nil
+ default:
+ return nil, errors.New("crypto/tls: found unknown private key type in PKCS#8 wrapping")
+ }
+ }
+ if key, err := x509.ParseECPrivateKey(der); err == nil {
+ return key, nil
+ }
+
+ return nil, errors.New("crypto/tls: failed to parse private key")
+}
diff --git a/src/pkg/crypto/tls/tls_test.go b/src/pkg/crypto/tls/tls_test.go
new file mode 100644
index 000000000..38229014c
--- /dev/null
+++ b/src/pkg/crypto/tls/tls_test.go
@@ -0,0 +1,107 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tls
+
+import (
+ "testing"
+)
+
+var rsaCertPEM = `-----BEGIN CERTIFICATE-----
+MIIB0zCCAX2gAwIBAgIJAI/M7BYjwB+uMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTIwOTEyMjE1MjAyWhcNMTUwOTEyMjE1MjAyWjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANLJ
+hPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wok/4xIA+ui35/MmNa
+rtNuC+BdZ1tMuVCPFZcCAwEAAaNQME4wHQYDVR0OBBYEFJvKs8RfJaXTH08W+SGv
+zQyKn0H8MB8GA1UdIwQYMBaAFJvKs8RfJaXTH08W+SGvzQyKn0H8MAwGA1UdEwQF
+MAMBAf8wDQYJKoZIhvcNAQEFBQADQQBJlffJHybjDGxRMqaRmDhX0+6v02TUKZsW
+r5QuVbpQhH6u+0UgcW0jp9QwpxoPTLTWGXEWBBBurxFwiCBhkQ+V
+-----END CERTIFICATE-----
+`
+
+var rsaKeyPEM = `-----BEGIN RSA PRIVATE KEY-----
+MIIBOwIBAAJBANLJhPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wo
+k/4xIA+ui35/MmNartNuC+BdZ1tMuVCPFZcCAwEAAQJAEJ2N+zsR0Xn8/Q6twa4G
+6OB1M1WO+k+ztnX/1SvNeWu8D6GImtupLTYgjZcHufykj09jiHmjHx8u8ZZB/o1N
+MQIhAPW+eyZo7ay3lMz1V01WVjNKK9QSn1MJlb06h/LuYv9FAiEA25WPedKgVyCW
+SmUwbPw8fnTcpqDWE3yTO3vKcebqMSsCIBF3UmVue8YU3jybC3NxuXq3wNm34R8T
+xVLHwDXh/6NJAiEAl2oHGGLz64BuAfjKrqwz7qMYr9HCLIe/YsoWq/olzScCIQDi
+D2lWusoe2/nEqfDVVWGWlyJ7yOmqaVm/iNUN9B2N2g==
+-----END RSA PRIVATE KEY-----
+`
+
+// keyPEM is the same as rsaKeyPEM, but declares itself as just
+// "PRIVATE KEY", not "RSA PRIVATE KEY". http://golang.org/issue/4477
+var keyPEM = `-----BEGIN PRIVATE KEY-----
+MIIBOwIBAAJBANLJhPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wo
+k/4xIA+ui35/MmNartNuC+BdZ1tMuVCPFZcCAwEAAQJAEJ2N+zsR0Xn8/Q6twa4G
+6OB1M1WO+k+ztnX/1SvNeWu8D6GImtupLTYgjZcHufykj09jiHmjHx8u8ZZB/o1N
+MQIhAPW+eyZo7ay3lMz1V01WVjNKK9QSn1MJlb06h/LuYv9FAiEA25WPedKgVyCW
+SmUwbPw8fnTcpqDWE3yTO3vKcebqMSsCIBF3UmVue8YU3jybC3NxuXq3wNm34R8T
+xVLHwDXh/6NJAiEAl2oHGGLz64BuAfjKrqwz7qMYr9HCLIe/YsoWq/olzScCIQDi
+D2lWusoe2/nEqfDVVWGWlyJ7yOmqaVm/iNUN9B2N2g==
+-----END PRIVATE KEY-----
+`
+
+var ecdsaCertPEM = `-----BEGIN CERTIFICATE-----
+MIIB/jCCAWICCQDscdUxw16XFDAJBgcqhkjOPQQBMEUxCzAJBgNVBAYTAkFVMRMw
+EQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0
+eSBMdGQwHhcNMTIxMTE0MTI0MDQ4WhcNMTUxMTE0MTI0MDQ4WjBFMQswCQYDVQQG
+EwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lk
+Z2l0cyBQdHkgTHRkMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBY9+my9OoeSUR
+lDQdV/x8LsOuLilthhiS1Tz4aGDHIPwC1mlvnf7fg5lecYpMCrLLhauAc1UJXcgl
+01xoLuzgtAEAgv2P/jgytzRSpUYvgLBt1UA0leLYBy6mQQbrNEuqT3INapKIcUv8
+XxYP0xMEUksLPq6Ca+CRSqTtrd/23uTnapkwCQYHKoZIzj0EAQOBigAwgYYCQXJo
+A7Sl2nLVf+4Iu/tAX/IF4MavARKC4PPHK3zfuGfPR3oCCcsAoz3kAzOeijvd0iXb
+H5jBImIxPL4WxQNiBTexAkF8D1EtpYuWdlVQ80/h/f4pBcGiXPqX5h2PQSQY7hP1
++jwM1FGS4fREIOvlBYr/SzzQRtwrvrzGYxDEDbsC0ZGRnA==
+-----END CERTIFICATE-----
+`
+
+var ecdsaKeyPEM = `-----BEGIN EC PARAMETERS-----
+BgUrgQQAIw==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MIHcAgEBBEIBrsoKp0oqcv6/JovJJDoDVSGWdirrkgCWxrprGlzB9o0X8fV675X0
+NwuBenXFfeZvVcwluO7/Q9wkYoPd/t3jGImgBwYFK4EEACOhgYkDgYYABAFj36bL
+06h5JRGUNB1X/Hwuw64uKW2GGJLVPPhoYMcg/ALWaW+d/t+DmV5xikwKssuFq4Bz
+VQldyCXTXGgu7OC0AQCC/Y/+ODK3NFKlRi+AsG3VQDSV4tgHLqZBBus0S6pPcg1q
+kohxS/xfFg/TEwRSSws+roJr4JFKpO2t3/be5OdqmQ==
+-----END EC PRIVATE KEY-----
+`
+
+var keyPairTests = []struct {
+ algo string
+ cert string
+ key string
+}{
+ {"ECDSA", ecdsaCertPEM, ecdsaKeyPEM},
+ {"RSA", rsaCertPEM, rsaKeyPEM},
+ {"RSA-untyped", rsaCertPEM, keyPEM}, // golang.org/issue/4477
+}
+
+func TestX509KeyPair(t *testing.T) {
+ var pem []byte
+ for _, test := range keyPairTests {
+ pem = []byte(test.cert + test.key)
+ if _, err := X509KeyPair(pem, pem); err != nil {
+ t.Errorf("Failed to load %s cert followed by %s key: %s", test.algo, test.algo, err)
+ }
+ pem = []byte(test.key + test.cert)
+ if _, err := X509KeyPair(pem, pem); err != nil {
+ t.Errorf("Failed to load %s key followed by %s cert: %s", test.algo, test.algo, err)
+ }
+ }
+}
+
+func TestX509MixedKeyPair(t *testing.T) {
+ if _, err := X509KeyPair([]byte(rsaCertPEM), []byte(ecdsaKeyPEM)); err == nil {
+ t.Error("Load of RSA certificate succeeded with ECDSA private key")
+ }
+ if _, err := X509KeyPair([]byte(ecdsaCertPEM), []byte(rsaKeyPEM)); err == nil {
+ t.Error("Load of ECDSA certificate succeeded with RSA private key")
+ }
+}
diff --git a/src/pkg/crypto/x509/cert_pool.go b/src/pkg/crypto/x509/cert_pool.go
index 616a0b3c1..505f4d4f7 100644
--- a/src/pkg/crypto/x509/cert_pool.go
+++ b/src/pkg/crypto/x509/cert_pool.go
@@ -103,7 +103,7 @@ 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.
+// all of the certificates in the pool.
func (s *CertPool) Subjects() (res [][]byte) {
res = make([][]byte, len(s.certs))
for i, c := range s.certs {
diff --git a/src/pkg/crypto/x509/pem_decrypt.go b/src/pkg/crypto/x509/pem_decrypt.go
new file mode 100644
index 000000000..194c81bf6
--- /dev/null
+++ b/src/pkg/crypto/x509/pem_decrypt.go
@@ -0,0 +1,233 @@
+// 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 x509
+
+// RFC 1423 describes the encryption of PEM blocks. The algorithm used to
+// generate a key from the password was derived by looking at the OpenSSL
+// implementation.
+
+import (
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/des"
+ "crypto/md5"
+ "encoding/hex"
+ "encoding/pem"
+ "errors"
+ "io"
+ "strings"
+)
+
+type PEMCipher int
+
+// Possible values for the EncryptPEMBlock encryption algorithm.
+const (
+ _ PEMCipher = iota
+ PEMCipherDES
+ PEMCipher3DES
+ PEMCipherAES128
+ PEMCipherAES192
+ PEMCipherAES256
+)
+
+// rfc1423Algo holds a method for enciphering a PEM block.
+type rfc1423Algo struct {
+ cipher PEMCipher
+ name string
+ cipherFunc func(key []byte) (cipher.Block, error)
+ keySize int
+ blockSize int
+}
+
+// rfc1423Algos holds a slice of the possible ways to encrypt a PEM
+// block. The ivSize numbers were taken from the OpenSSL source.
+var rfc1423Algos = []rfc1423Algo{{
+ cipher: PEMCipherDES,
+ name: "DES-CBC",
+ cipherFunc: des.NewCipher,
+ keySize: 8,
+ blockSize: des.BlockSize,
+}, {
+ cipher: PEMCipher3DES,
+ name: "DES-EDE3-CBC",
+ cipherFunc: des.NewTripleDESCipher,
+ keySize: 24,
+ blockSize: des.BlockSize,
+}, {
+ cipher: PEMCipherAES128,
+ name: "AES-128-CBC",
+ cipherFunc: aes.NewCipher,
+ keySize: 16,
+ blockSize: aes.BlockSize,
+}, {
+ cipher: PEMCipherAES192,
+ name: "AES-192-CBC",
+ cipherFunc: aes.NewCipher,
+ keySize: 24,
+ blockSize: aes.BlockSize,
+}, {
+ cipher: PEMCipherAES256,
+ name: "AES-256-CBC",
+ cipherFunc: aes.NewCipher,
+ keySize: 32,
+ blockSize: aes.BlockSize,
+},
+}
+
+// deriveKey uses a key derivation function to stretch the password into a key
+// with the number of bits our cipher requires. This algorithm was derived from
+// the OpenSSL source.
+func (c rfc1423Algo) deriveKey(password, salt []byte) []byte {
+ hash := md5.New()
+ out := make([]byte, c.keySize)
+ var digest []byte
+
+ for i := 0; i < len(out); i += len(digest) {
+ hash.Reset()
+ hash.Write(digest)
+ hash.Write(password)
+ hash.Write(salt)
+ digest = hash.Sum(digest[:0])
+ copy(out[i:], digest)
+ }
+ return out
+}
+
+// IsEncryptedPEMBlock returns if the PEM block is password encrypted.
+func IsEncryptedPEMBlock(b *pem.Block) bool {
+ _, ok := b.Headers["DEK-Info"]
+ return ok
+}
+
+// IncorrectPasswordError is returned when an incorrect password is detected.
+var IncorrectPasswordError = errors.New("x509: decryption password incorrect")
+
+// DecryptPEMBlock takes a password encrypted PEM block and the password used to
+// encrypt it and returns a slice of decrypted DER encoded bytes. It inspects
+// the DEK-Info header to determine the algorithm used for decryption. If no
+// DEK-Info header is present, an error is returned. If an incorrect password
+// is detected an IncorrectPasswordError is returned.
+func DecryptPEMBlock(b *pem.Block, password []byte) ([]byte, error) {
+ dek, ok := b.Headers["DEK-Info"]
+ if !ok {
+ return nil, errors.New("x509: no DEK-Info header in block")
+ }
+
+ idx := strings.Index(dek, ",")
+ if idx == -1 {
+ return nil, errors.New("x509: malformed DEK-Info header")
+ }
+
+ mode, hexIV := dek[:idx], dek[idx+1:]
+ ciph := cipherByName(mode)
+ if ciph == nil {
+ return nil, errors.New("x509: unknown encryption mode")
+ }
+ iv, err := hex.DecodeString(hexIV)
+ if err != nil {
+ return nil, err
+ }
+ if len(iv) != ciph.blockSize {
+ return nil, errors.New("x509: incorrect IV size")
+ }
+
+ // Based on the OpenSSL implementation. The salt is the first 8 bytes
+ // of the initialization vector.
+ key := ciph.deriveKey(password, iv[:8])
+ block, err := ciph.cipherFunc(key)
+ if err != nil {
+ return nil, err
+ }
+
+ data := make([]byte, len(b.Bytes))
+ dec := cipher.NewCBCDecrypter(block, iv)
+ dec.CryptBlocks(data, b.Bytes)
+
+ // Blocks are padded using a scheme where the last n bytes of padding are all
+ // equal to n. It can pad from 1 to blocksize bytes inclusive. See RFC 1423.
+ // For example:
+ // [x y z 2 2]
+ // [x y 7 7 7 7 7 7 7]
+ // If we detect a bad padding, we assume it is an invalid password.
+ dlen := len(data)
+ if dlen == 0 || dlen%ciph.blockSize != 0 {
+ return nil, errors.New("x509: invalid padding")
+ }
+ last := int(data[dlen-1])
+ if dlen < last {
+ return nil, IncorrectPasswordError
+ }
+ if last == 0 || last > ciph.blockSize {
+ return nil, IncorrectPasswordError
+ }
+ for _, val := range data[dlen-last:] {
+ if int(val) != last {
+ return nil, IncorrectPasswordError
+ }
+ }
+ return data[:dlen-last], nil
+}
+
+// EncryptPEMBlock returns a PEM block of the specified type holding the
+// given DER-encoded data encrypted with the specified algorithm and
+// password.
+func EncryptPEMBlock(rand io.Reader, blockType string, data, password []byte, alg PEMCipher) (*pem.Block, error) {
+ ciph := cipherByKey(alg)
+ if ciph == nil {
+ return nil, errors.New("x509: unknown encryption mode")
+ }
+ iv := make([]byte, ciph.blockSize)
+ if _, err := io.ReadFull(rand, iv); err != nil {
+ return nil, errors.New("x509: cannot generate IV: " + err.Error())
+ }
+ // The salt is the first 8 bytes of the initialization vector,
+ // matching the key derivation in DecryptPEMBlock.
+ key := ciph.deriveKey(password, iv[:8])
+ block, err := ciph.cipherFunc(key)
+ if err != nil {
+ return nil, err
+ }
+ enc := cipher.NewCBCEncrypter(block, iv)
+ pad := ciph.blockSize - len(data)%ciph.blockSize
+ encrypted := make([]byte, len(data), len(data)+pad)
+ // We could save this copy by encrypting all the whole blocks in
+ // the data separately, but it doesn't seem worth the additional
+ // code.
+ copy(encrypted, data)
+ // See RFC 1423, section 1.1
+ for i := 0; i < pad; i++ {
+ encrypted = append(encrypted, byte(pad))
+ }
+ enc.CryptBlocks(encrypted, encrypted)
+
+ return &pem.Block{
+ Type: blockType,
+ Headers: map[string]string{
+ "Proc-Type": "4,ENCRYPTED",
+ "DEK-Info": ciph.name + "," + hex.EncodeToString(iv),
+ },
+ Bytes: encrypted,
+ }, nil
+}
+
+func cipherByName(name string) *rfc1423Algo {
+ for i := range rfc1423Algos {
+ alg := &rfc1423Algos[i]
+ if alg.name == name {
+ return alg
+ }
+ }
+ return nil
+}
+
+func cipherByKey(key PEMCipher) *rfc1423Algo {
+ for i := range rfc1423Algos {
+ alg := &rfc1423Algos[i]
+ if alg.cipher == key {
+ return alg
+ }
+ }
+ return nil
+}
diff --git a/src/pkg/crypto/x509/pem_decrypt_test.go b/src/pkg/crypto/x509/pem_decrypt_test.go
new file mode 100644
index 000000000..59ba6f900
--- /dev/null
+++ b/src/pkg/crypto/x509/pem_decrypt_test.go
@@ -0,0 +1,223 @@
+// 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 x509
+
+import (
+ "bytes"
+ "crypto/rand"
+ "encoding/base64"
+ "encoding/pem"
+ "testing"
+)
+
+func TestDecrypt(t *testing.T) {
+ for i, data := range testData {
+ t.Logf("test %d. %s", i, data.kind)
+ block, rest := pem.Decode(data.pemData)
+ if len(rest) > 0 {
+ t.Error("extra data")
+ }
+ der, err := DecryptPEMBlock(block, data.password)
+ if err != nil {
+ t.Error("decrypt failed: ", err)
+ continue
+ }
+ if _, err := ParsePKCS1PrivateKey(der); err != nil {
+ t.Error("invalid private key: ", err)
+ }
+ plainDER, err := base64.StdEncoding.DecodeString(data.plainDER)
+ if err != nil {
+ t.Fatal("cannot decode test DER data: ", err)
+ }
+ if !bytes.Equal(der, plainDER) {
+ t.Error("data mismatch")
+ }
+ }
+}
+
+func TestEncrypt(t *testing.T) {
+ for i, data := range testData {
+ t.Logf("test %d. %s", i, data.kind)
+ plainDER, err := base64.StdEncoding.DecodeString(data.plainDER)
+ if err != nil {
+ t.Fatal("cannot decode test DER data: ", err)
+ }
+ password := []byte("kremvax1")
+ block, err := EncryptPEMBlock(rand.Reader, "RSA PRIVATE KEY", plainDER, password, data.kind)
+ if err != nil {
+ t.Error("encrypt: ", err)
+ continue
+ }
+ if !IsEncryptedPEMBlock(block) {
+ t.Error("PEM block does not appear to be encrypted")
+ }
+ if block.Type != "RSA PRIVATE KEY" {
+ t.Errorf("unexpected block type; got %q want %q", block.Type, "RSA PRIVATE KEY")
+ }
+ if block.Headers["Proc-Type"] != "4,ENCRYPTED" {
+ t.Errorf("block does not have correct Proc-Type header")
+ }
+ der, err := DecryptPEMBlock(block, password)
+ if err != nil {
+ t.Error("decrypt: ", err)
+ continue
+ }
+ if !bytes.Equal(der, plainDER) {
+ t.Errorf("data mismatch")
+ }
+ }
+}
+
+var testData = []struct {
+ kind PEMCipher
+ password []byte
+ pemData []byte
+ plainDER string
+}{
+ {
+ kind: PEMCipherDES,
+ password: []byte("asdf"),
+ pemData: []byte(`
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-CBC,34F09A4FC8DE22B5
+
+WXxy8kbZdiZvANtKvhmPBLV7eVFj2A5z6oAxvI9KGyhG0ZK0skfnt00C24vfU7m5
+ICXeoqP67lzJ18xCzQfHjDaBNs53DSDT+Iz4e8QUep1xQ30+8QKX2NA2coee3nwc
+6oM1cuvhNUDemBH2i3dKgMVkfaga0zQiiOq6HJyGSncCMSruQ7F9iWEfRbFcxFCx
+qtHb1kirfGKEtgWTF+ynyco6+2gMXNu70L7nJcnxnV/RLFkHt7AUU1yrclxz7eZz
+XOH9VfTjb52q/I8Suozq9coVQwg4tXfIoYUdT//O+mB7zJb9HI9Ps77b9TxDE6Gm
+4C9brwZ3zg2vqXcwwV6QRZMtyll9rOpxkbw6NPlpfBqkc3xS51bbxivbO/Nve4KD
+r12ymjFNF4stXCfJnNqKoZ50BHmEEUDu5Wb0fpVn82XrGw7CYc4iug==
+-----END RSA PRIVATE KEY-----`),
+ plainDER: `
+MIIBPAIBAAJBAPASZe+tCPU6p80AjHhDkVsLYa51D35e/YGa8QcZyooeZM8EHozo
+KD0fNiKI+53bHdy07N+81VQ8/ejPcRoXPlsCAwEAAQJBAMTxIuSq27VpR+zZ7WJf
+c6fvv1OBvpMZ0/d1pxL/KnOAgq2rD5hDtk9b0LGhTPgQAmrrMTKuSeGoIuYE+gKQ
+QvkCIQD+GC1m+/do+QRurr0uo46Kx1LzLeSCrjBk34wiOp2+dwIhAPHfTLRXS2fv
+7rljm0bYa4+eDZpz+E8RcXEgzhhvcQQ9AiAI5eHZJGOyml3MXnQjiPi55WcDOw0w
+glcRgT6QCEtz2wIhANSyqaFtosIkHKqrDUGfz/bb5tqMYTAnBruVPaf/WEOBAiEA
+9xORWeRG1tRpso4+dYy4KdDkuLPIO01KY6neYGm3BCM=`,
+ },
+ {
+ kind: PEMCipher3DES,
+ password: []byte("asdf"),
+ pemData: []byte(`
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,C1F4A6A03682C2C7
+
+0JqVdBEH6iqM7drTkj+e2W/bE3LqakaiWhb9WUVonFkhyu8ca/QzebY3b5gCvAZQ
+YwBvDcT/GHospKqPx+cxDHJNsUASDZws6bz8ZXWJGwZGExKzr0+Qx5fgXn44Ms3x
+8g1ENFuTXtxo+KoNK0zuAMAqp66Llcds3Fjl4XR18QaD0CrVNAfOdgATWZm5GJxk
+Fgx5f84nT+/ovvreG+xeOzWgvtKo0UUZVrhGOgfKLpa57adumcJ6SkUuBtEFpZFB
+ldw5w7WC7d13x2LsRkwo8ZrDKgIV+Y9GNvhuCCkTzNP0V3gNeJpd201HZHR+9n3w
+3z0VjR/MGqsfcy1ziEWMNOO53At3zlG6zP05aHMnMcZoVXadEK6L1gz++inSSDCq
+gI0UJP4e3JVB7AkgYymYAwiYALAkoEIuanxoc50njJk=
+-----END RSA PRIVATE KEY-----`),
+ plainDER: `
+MIIBOwIBAAJBANOCXKdoNS/iP/MAbl9cf1/SF3P+Ns7ZeNL27CfmDh0O6Zduaax5
+NBiumd2PmjkaCu7lQ5JOibHfWn+xJsc3kw0CAwEAAQJANX/W8d1Q/sCqzkuAn4xl
+B5a7qfJWaLHndu1QRLNTRJPn0Ee7OKJ4H0QKOhQM6vpjRrz+P2u9thn6wUxoPsef
+QQIhAP/jCkfejFcy4v15beqKzwz08/tslVjF+Yq41eJGejmxAiEA05pMoqfkyjcx
+fyvGhpoOyoCp71vSGUfR2I9CR65oKh0CIC1Msjs66LlfJtQctRq6bCEtFCxEcsP+
+eEjYo/Sk6WphAiEAxpgWPMJeU/shFT28gS+tmhjPZLpEoT1qkVlC14u0b3ECIQDX
+tZZZxCtPAm7shftEib0VU77Lk8MsXJcx2C4voRsjEw==`,
+ },
+ {
+ kind: PEMCipherAES128,
+ password: []byte("asdf"),
+ pemData: []byte(`
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,D4492E793FC835CC038A728ED174F78A
+
+EyfQSzXSjv6BaNH+NHdXRlkHdimpF9izWlugVJAPApgXrq5YldPe2aGIOFXyJ+QE
+ZIG20DYqaPzJRjTEbPNZ6Es0S2JJ5yCpKxwJuDkgJZKtF39Q2i36JeGbSZQIuWJE
+GZbBpf1jDH/pr0iGonuAdl2PCCZUiy+8eLsD2tyviHUkFLOB+ykYoJ5t8ngZ/B6D
+33U43LLb7+9zD4y3Q9OVHqBFGyHcxCY9+9Qh4ZnFp7DTf6RY5TNEvE3s4g6aDpBs
+3NbvRVvYTgs8K9EPk4K+5R+P2kD8J8KvEIGxVa1vz8QoCJ/jr7Ka2rvNgPCex5/E
+080LzLHPCrXKdlr/f50yhNWq08ZxMWQFkui+FDHPDUaEELKAXV8/5PDxw80Rtybo
+AVYoCVIbZXZCuCO81op8UcOgEpTtyU5Lgh3Mw5scQL0=
+-----END RSA PRIVATE KEY-----`),
+ plainDER: `
+MIIBOgIBAAJBAMBlj5FxYtqbcy8wY89d/S7n0+r5MzD9F63BA/Lpl78vQKtdJ5dT
+cDGh/rBt1ufRrNp0WihcmZi7Mpl/3jHjiWECAwEAAQJABNOHYnKhtDIqFYj1OAJ3
+k3GlU0OlERmIOoeY/cL2V4lgwllPBEs7r134AY4wMmZSBUj8UR/O4SNO668ElKPE
+cQIhAOuqY7/115x5KCdGDMWi+jNaMxIvI4ETGwV40ykGzqlzAiEA0P9oEC3m9tHB
+kbpjSTxaNkrXxDgdEOZz8X0uOUUwHNsCIAwzcSCiGLyYJTULUmP1ESERfW1mlV78
+XzzESaJpIM/zAiBQkSTcl9VhcJreQqvjn5BnPZLP4ZHS4gPwJAGdsj5J4QIhAOVR
+B3WlRNTXR2WsJ5JdByezg9xzdXzULqmga0OE339a`,
+ },
+ {
+ kind: PEMCipherAES192,
+ password: []byte("asdf"),
+ pemData: []byte(`
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-192-CBC,E2C9FB02BCA23ADE1829F8D8BC5F5369
+
+cqVslvHqDDM6qwU6YjezCRifXmKsrgEev7ng6Qs7UmDJOpHDgJQZI9fwMFUhIyn5
+FbCu1SHkLMW52Ld3CuEqMnzWMlhPrW8tFvUOrMWPYSisv7nNq88HobZEJcUNL2MM
+Y15XmHW6IJwPqhKyLHpWXyOCVEh4ODND2nV15PCoi18oTa475baxSk7+1qH7GuIs
+Rb7tshNTMqHbCpyo9Rn3UxeFIf9efdl8YLiMoIqc7J8E5e9VlbeQSdLMQOgDAQJG
+ReUtTw8exmKsY4gsSjhkg5uiw7/ZB1Ihto0qnfQJgjGc680qGkT1d6JfvOfeYAk6
+xn5RqS/h8rYAYm64KnepfC9vIujo4NqpaREDmaLdX5MJPQ+SlytITQvgUsUq3q/t
+Ss85xjQEZH3hzwjQqdJvmA4hYP6SUjxYpBM+02xZ1Xw=
+-----END RSA PRIVATE KEY-----`),
+ plainDER: `
+MIIBOwIBAAJBAMGcRrZiNNmtF20zyS6MQ7pdGx17aFDl+lTl+qnLuJRUCMUG05xs
+OmxmL/O1Qlf+bnqR8Bgg65SfKg21SYuLhiMCAwEAAQJBAL94uuHyO4wux2VC+qpj
+IzPykjdU7XRcDHbbvksf4xokSeUFjjD3PB0Qa83M94y89ZfdILIqS9x5EgSB4/lX
+qNkCIQD6cCIqLfzq/lYbZbQgAAjpBXeQVYsbvVtJrPrXJAlVVQIhAMXpDKMeFPMn
+J0g2rbx1gngx0qOa5r5iMU5w/noN4W2XAiBjf+WzCG5yFvazD+dOx3TC0A8+4x3P
+uZ3pWbaXf5PNuQIgAcdXarvhelH2w2piY1g3BPeFqhzBSCK/yLGxR82KIh8CIQDD
++qGKsd09NhQ/G27y/DARzOYtml1NvdmCQAgsDIIOLA==`,
+ },
+ {
+ kind: PEMCipherAES256,
+ password: []byte("asdf"),
+ pemData: []byte(`
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,8E7ED5CD731902CE938957A886A5FFBD
+
+4Mxr+KIzRVwoOP0wwq6caSkvW0iS+GE2h2Ov/u+n9ZTMwL83PRnmjfjzBgfRZLVf
+JFPXxUK26kMNpIdssNnqGOds+DhB+oSrsNKoxgxSl5OBoYv9eJTVYm7qOyAFIsjr
+DRKAcjYCmzfesr7PVTowwy0RtHmYwyXMGDlAzzZrEvaiySFFmMyKKvtoavwaFoc7
+Pz3RZScwIuubzTGJ1x8EzdffYOsdCa9Mtgpp3L136+23dOd6L/qK2EG2fzrJSHs/
+2XugkleBFSMKzEp9mxXKRfa++uidQvMZTFLDK9w5YjrRvMBo/l2BoZIsq0jAIE1N
+sv5Z/KwlX+3MDEpPQpUwGPlGGdLnjI3UZ+cjgqBcoMiNc6HfgbBgYJSU6aDSHuCk
+clCwByxWkBNgJ2GrkwNrF26v+bGJJJNR4SKouY1jQf0=
+-----END RSA PRIVATE KEY-----`),
+ plainDER: `
+MIIBOgIBAAJBAKy3GFkstoCHIEeUU/qO8207m8WSrjksR+p9B4tf1w5k+2O1V/GY
+AQ5WFCApItcOkQe/I0yZZJk/PmCqMzSxrc8CAwEAAQJAOCAz0F7AW9oNelVQSP8F
+Sfzx7O1yom+qWyAQQJF/gFR11gpf9xpVnnyu1WxIRnDUh1LZwUsjwlDYb7MB74id
+oQIhANPcOiLwOPT4sIUpRM5HG6BF1BI7L77VpyGVk8xNP7X/AiEA0LMHZtk4I+lJ
+nClgYp4Yh2JZ1Znbu7IoQMCEJCjwKDECIGd8Dzm5tViTkUW6Hs3Tlf73nNs65duF
+aRnSglss8I3pAiEAonEnKruawgD8RavDFR+fUgmQiPz4FnGGeVgfwpGG1JECIBYq
+PXHYtPqxQIbD2pScR5qum7iGUh11lEUPkmt+2uqS`,
+ },
+ {
+ // generated with:
+ // openssl genrsa -aes128 -passout pass:asdf -out server.orig.key 128
+ kind: PEMCipherAES128,
+ password: []byte("asdf"),
+ pemData: []byte(`
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,74611ABC2571AF11B1BF9B69E62C89E7
+
+6ei/MlytjE0FFgZOGQ+jrwomKfpl8kdefeE0NSt/DMRrw8OacHAzBNi3pPEa0eX3
+eND9l7C9meCirWovjj9QWVHrXyugFuDIqgdhQ8iHTgCfF3lrmcttVrbIfMDw+smD
+hTP8O1mS/MHl92NE0nhv0w==
+-----END RSA PRIVATE KEY-----`),
+ plainDER: `
+MGMCAQACEQC6ssxmYuauuHGOCDAI54RdAgMBAAECEQCWIn6Yv2O+kBcDF7STctKB
+AgkA8SEfu/2i3g0CCQDGNlXbBHX7kQIIK3Ww5o0cYbECCQDCimPb0dYGsQIIeQ7A
+jryIst8=`,
+ },
+}
diff --git a/src/pkg/crypto/x509/pkcs8.go b/src/pkg/crypto/x509/pkcs8.go
index 4d8e0518e..30caacb3c 100644
--- a/src/pkg/crypto/x509/pkcs8.go
+++ b/src/pkg/crypto/x509/pkcs8.go
@@ -11,8 +11,9 @@ import (
"fmt"
)
-// pkcs8 reflects an ASN.1, PKCS#8 PrivateKey. See
-// ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-8/pkcs-8v1_2.asn.
+// pkcs8 reflects an ASN.1, PKCS#8 PrivateKey. See
+// ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-8/pkcs-8v1_2.asn
+// and RFC5208.
type pkcs8 struct {
Version int
Algo pkix.AlgorithmIdentifier
@@ -21,19 +22,32 @@ type pkcs8 struct {
}
// ParsePKCS8PrivateKey parses an unencrypted, PKCS#8 private key. See
-// http://www.rsa.com/rsalabs/node.asp?id=2130
+// http://www.rsa.com/rsalabs/node.asp?id=2130 and RFC5208.
func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) {
var privKey pkcs8
if _, err := asn1.Unmarshal(der, &privKey); err != nil {
return nil, err
}
switch {
- case privKey.Algo.Algorithm.Equal(oidRSA):
+ case privKey.Algo.Algorithm.Equal(oidPublicKeyRSA):
key, err = ParsePKCS1PrivateKey(privKey.PrivateKey)
if err != nil {
return nil, errors.New("crypto/x509: failed to parse RSA private key embedded in PKCS#8: " + err.Error())
}
return key, nil
+
+ case privKey.Algo.Algorithm.Equal(oidPublicKeyECDSA):
+ bytes := privKey.Algo.Parameters.FullBytes
+ namedCurveOID := new(asn1.ObjectIdentifier)
+ if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil {
+ namedCurveOID = nil
+ }
+ key, err = parseECPrivateKey(namedCurveOID, privKey.PrivateKey)
+ if err != nil {
+ return nil, errors.New("crypto/x509: failed to parse EC private key embedded in PKCS#8: " + err.Error())
+ }
+ return key, nil
+
default:
return nil, fmt.Errorf("crypto/x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm)
}
diff --git a/src/pkg/crypto/x509/pkcs8_test.go b/src/pkg/crypto/x509/pkcs8_test.go
index 372005f90..4114efd0e 100644
--- a/src/pkg/crypto/x509/pkcs8_test.go
+++ b/src/pkg/crypto/x509/pkcs8_test.go
@@ -9,12 +9,20 @@ import (
"testing"
)
-var pkcs8PrivateKeyHex = `30820278020100300d06092a864886f70d0101010500048202623082025e02010002818100cfb1b5bf9685ffa97b4f99df4ff122b70e59ac9b992f3bc2b3dde17d53c1a34928719b02e8fd17839499bfbd515bd6ef99c7a1c47a239718fe36bfd824c0d96060084b5f67f0273443007a24dfaf5634f7772c9346e10eb294c2306671a5a5e719ae24b4de467291bc571014b0e02dec04534d66a9bb171d644b66b091780e8d020301000102818100b595778383c4afdbab95d2bfed12b3f93bb0a73a7ad952f44d7185fd9ec6c34de8f03a48770f2009c8580bcd275e9632714e9a5e3f32f29dc55474b2329ff0ebc08b3ffcb35bc96e6516b483df80a4a59cceb71918cbabf91564e64a39d7e35dce21cb3031824fdbc845dba6458852ec16af5dddf51a8397a8797ae0337b1439024100ea0eb1b914158c70db39031dd8904d6f18f408c85fbbc592d7d20dee7986969efbda081fdf8bc40e1b1336d6b638110c836bfdc3f314560d2e49cd4fbde1e20b024100e32a4e793b574c9c4a94c8803db5152141e72d03de64e54ef2c8ed104988ca780cd11397bc359630d01b97ebd87067c5451ba777cf045ca23f5912f1031308c702406dfcdbbd5a57c9f85abc4edf9e9e29153507b07ce0a7ef6f52e60dcfebe1b8341babd8b789a837485da6c8d55b29bbb142ace3c24a1f5b54b454d01b51e2ad03024100bd6a2b60dee01e1b3bfcef6a2f09ed027c273cdbbaf6ba55a80f6dcc64e4509ee560f84b4f3e076bd03b11e42fe71a3fdd2dffe7e0902c8584f8cad877cdc945024100aa512fa4ada69881f1d8bb8ad6614f192b83200aef5edf4811313d5ef30a86cbd0a90f7b025c71ea06ec6b34db6306c86b1040670fd8654ad7291d066d06d031`
+var pkcs8RSAPrivateKeyHex = `30820278020100300d06092a864886f70d0101010500048202623082025e02010002818100cfb1b5bf9685ffa97b4f99df4ff122b70e59ac9b992f3bc2b3dde17d53c1a34928719b02e8fd17839499bfbd515bd6ef99c7a1c47a239718fe36bfd824c0d96060084b5f67f0273443007a24dfaf5634f7772c9346e10eb294c2306671a5a5e719ae24b4de467291bc571014b0e02dec04534d66a9bb171d644b66b091780e8d020301000102818100b595778383c4afdbab95d2bfed12b3f93bb0a73a7ad952f44d7185fd9ec6c34de8f03a48770f2009c8580bcd275e9632714e9a5e3f32f29dc55474b2329ff0ebc08b3ffcb35bc96e6516b483df80a4a59cceb71918cbabf91564e64a39d7e35dce21cb3031824fdbc845dba6458852ec16af5dddf51a8397a8797ae0337b1439024100ea0eb1b914158c70db39031dd8904d6f18f408c85fbbc592d7d20dee7986969efbda081fdf8bc40e1b1336d6b638110c836bfdc3f314560d2e49cd4fbde1e20b024100e32a4e793b574c9c4a94c8803db5152141e72d03de64e54ef2c8ed104988ca780cd11397bc359630d01b97ebd87067c5451ba777cf045ca23f5912f1031308c702406dfcdbbd5a57c9f85abc4edf9e9e29153507b07ce0a7ef6f52e60dcfebe1b8341babd8b789a837485da6c8d55b29bbb142ace3c24a1f5b54b454d01b51e2ad03024100bd6a2b60dee01e1b3bfcef6a2f09ed027c273cdbbaf6ba55a80f6dcc64e4509ee560f84b4f3e076bd03b11e42fe71a3fdd2dffe7e0902c8584f8cad877cdc945024100aa512fa4ada69881f1d8bb8ad6614f192b83200aef5edf4811313d5ef30a86cbd0a90f7b025c71ea06ec6b34db6306c86b1040670fd8654ad7291d066d06d031`
+
+// Generated using:
+// openssl ecparam -genkey -name secp521r1 | openssl pkcs8 -topk8 -nocrypt
+var pkcs8ECPrivateKeyHex = `3081ed020100301006072a8648ce3d020106052b810400230481d53081d20201010441850d81618c5da1aec74c2eed608ba816038506975e6427237c2def150c96a3b13efbfa1f89f1be15cdf4d0ac26422e680e65a0ddd4ad3541ad76165fbf54d6e34ba18189038186000400da97bcedba1eb6d30aeb93c9f9a1454598fa47278df27d6f60ea73eb672d8dc528a9b67885b5b5dcef93c9824f7449ab512ee6a27e76142f56b94b474cfd697e810046c8ca70419365245c1d7d44d0db82c334073835d002232714548abbae6e5700f5ef315ee08b929d8581383dcf2d1c98c2f8a9fccbf79c9579f7b2fd8a90115ac2`
func TestPKCS8(t *testing.T) {
- derBytes, _ := hex.DecodeString(pkcs8PrivateKeyHex)
- _, err := ParsePKCS8PrivateKey(derBytes)
- if err != nil {
- t.Errorf("failed to decode PKCS8 key: %s", err)
+ derBytes, _ := hex.DecodeString(pkcs8RSAPrivateKeyHex)
+ if _, err := ParsePKCS8PrivateKey(derBytes); err != nil {
+ t.Errorf("failed to decode PKCS8 with RSA private key: %s", err)
+ }
+
+ derBytes, _ = hex.DecodeString(pkcs8ECPrivateKeyHex)
+ if _, err := ParsePKCS8PrivateKey(derBytes); err != nil {
+ t.Errorf("failed to decode PKCS8 with EC private key: %s", err)
}
}
diff --git a/src/pkg/crypto/x509/root_darwin.go b/src/pkg/crypto/x509/root_darwin.go
index 0f99581e8..ad3bfb4b4 100644
--- a/src/pkg/crypto/x509/root_darwin.go
+++ b/src/pkg/crypto/x509/root_darwin.go
@@ -70,11 +70,12 @@ func initSystemRoots() {
var data C.CFDataRef = nil
err := C.FetchPEMRoots(&data)
- if err != -1 {
- defer C.CFRelease(C.CFTypeRef(data))
- buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data)))
- roots.AppendCertsFromPEM(buf)
+ if err == -1 {
+ return
}
+ defer C.CFRelease(C.CFTypeRef(data))
+ buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data)))
+ roots.AppendCertsFromPEM(buf)
systemRoots = roots
}
diff --git a/src/pkg/crypto/x509/root_plan9.go b/src/pkg/crypto/x509/root_plan9.go
new file mode 100644
index 000000000..9965caade
--- /dev/null
+++ b/src/pkg/crypto/x509/root_plan9.go
@@ -0,0 +1,33 @@
+// 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 plan9
+
+package x509
+
+import "io/ioutil"
+
+// Possible certificate files; stop after finding one.
+var certFiles = []string{
+ "/sys/lib/tls/ca.pem",
+}
+
+func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
+ return nil, nil
+}
+
+func initSystemRoots() {
+ roots := NewCertPool()
+ for _, file := range certFiles {
+ data, err := ioutil.ReadFile(file)
+ if err == nil {
+ roots.AppendCertsFromPEM(data)
+ systemRoots = roots
+ return
+ }
+ }
+
+ // All of the files failed to load. systemRoots will be nil which will
+ // trigger a specific error at verification time.
+}
diff --git a/src/pkg/crypto/x509/root_stub.go b/src/pkg/crypto/x509/root_stub.go
index 568004108..4c742ccc3 100644
--- a/src/pkg/crypto/x509/root_stub.go
+++ b/src/pkg/crypto/x509/root_stub.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 plan9 darwin,!cgo
+// +build darwin,!cgo
package x509
@@ -11,5 +11,4 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate
}
func initSystemRoots() {
- systemRoots = NewCertPool()
}
diff --git a/src/pkg/crypto/x509/root_unix.go b/src/pkg/crypto/x509/root_unix.go
index 76e79f494..1b25a94d0 100644
--- a/src/pkg/crypto/x509/root_unix.go
+++ b/src/pkg/crypto/x509/root_unix.go
@@ -27,9 +27,11 @@ func initSystemRoots() {
data, err := ioutil.ReadFile(file)
if err == nil {
roots.AppendCertsFromPEM(data)
- break
+ systemRoots = roots
+ return
}
}
- systemRoots = roots
+ // All of the files failed to load. systemRoots will be nil which will
+ // trigger a specific error at verification time.
}
diff --git a/src/pkg/crypto/x509/root_windows.go b/src/pkg/crypto/x509/root_windows.go
index 7e8f2af4b..e8f70a49d 100644
--- a/src/pkg/crypto/x509/root_windows.go
+++ b/src/pkg/crypto/x509/root_windows.go
@@ -98,9 +98,13 @@ func checkChainTrustStatus(c *Certificate, chainCtx *syscall.CertChainContext) e
// checkChainSSLServerPolicy checks that the certificate chain in chainCtx is valid for
// use as a certificate chain for a SSL/TLS server.
func checkChainSSLServerPolicy(c *Certificate, chainCtx *syscall.CertChainContext, opts *VerifyOptions) error {
+ servernamep, err := syscall.UTF16PtrFromString(opts.DNSName)
+ if err != nil {
+ return err
+ }
sslPara := &syscall.SSLExtraCertChainPolicyPara{
AuthType: syscall.AUTHTYPE_SERVER,
- ServerName: syscall.StringToUTF16Ptr(opts.DNSName),
+ ServerName: servernamep,
}
sslPara.Size = uint32(unsafe.Sizeof(*sslPara))
@@ -110,7 +114,7 @@ func checkChainSSLServerPolicy(c *Certificate, chainCtx *syscall.CertChainContex
para.Size = uint32(unsafe.Sizeof(*para))
status := syscall.CertChainPolicyStatus{}
- err := syscall.CertVerifyCertificateChainPolicy(syscall.CERT_CHAIN_POLICY_SSL, chainCtx, para, &status)
+ err = syscall.CertVerifyCertificateChainPolicy(syscall.CERT_CHAIN_POLICY_SSL, chainCtx, para, &status)
if err != nil {
return err
}
@@ -222,5 +226,4 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate
}
func initSystemRoots() {
- systemRoots = NewCertPool()
}
diff --git a/src/pkg/crypto/x509/sec1.go b/src/pkg/crypto/x509/sec1.go
new file mode 100644
index 000000000..8a2840fbe
--- /dev/null
+++ b/src/pkg/crypto/x509/sec1.go
@@ -0,0 +1,69 @@
+// 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 x509
+
+import (
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "encoding/asn1"
+ "errors"
+ "fmt"
+ "math/big"
+)
+
+const ecPrivKeyVersion = 1
+
+// ecPrivateKey reflects an ASN.1 Elliptic Curve Private Key Structure.
+// References:
+// RFC5915
+// SEC1 - http://www.secg.org/download/aid-780/sec1-v2.pdf
+// Per RFC5915 the NamedCurveOID is marked as ASN.1 OPTIONAL, however in
+// most cases it is not.
+type ecPrivateKey struct {
+ Version int
+ PrivateKey []byte
+ NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"`
+ PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"`
+}
+
+// ParseECPrivateKey parses an ASN.1 Elliptic Curve Private Key Structure.
+func ParseECPrivateKey(der []byte) (key *ecdsa.PrivateKey, err error) {
+ return parseECPrivateKey(nil, der)
+}
+
+// parseECPrivateKey parses an ASN.1 Elliptic Curve Private Key Structure.
+// The OID for the named curve may be provided from another source (such as
+// the PKCS8 container) - if it is provided then use this instead of the OID
+// that may exist in the EC private key structure.
+func parseECPrivateKey(namedCurveOID *asn1.ObjectIdentifier, der []byte) (key *ecdsa.PrivateKey, err error) {
+ var privKey ecPrivateKey
+ if _, err := asn1.Unmarshal(der, &privKey); err != nil {
+ return nil, errors.New("crypto/x509: failed to parse EC private key: " + err.Error())
+ }
+ if privKey.Version != ecPrivKeyVersion {
+ return nil, fmt.Errorf("crypto/x509: unknown EC private key version %d", privKey.Version)
+ }
+
+ var curve elliptic.Curve
+ if namedCurveOID != nil {
+ curve = namedCurveFromOID(*namedCurveOID)
+ } else {
+ curve = namedCurveFromOID(privKey.NamedCurveOID)
+ }
+ if curve == nil {
+ return nil, errors.New("crypto/x509: unknown elliptic curve")
+ }
+
+ k := new(big.Int).SetBytes(privKey.PrivateKey)
+ if k.Cmp(curve.Params().N) >= 0 {
+ return nil, errors.New("crypto/x509: invalid elliptic curve private key value")
+ }
+ priv := new(ecdsa.PrivateKey)
+ priv.Curve = curve
+ priv.D = k
+ priv.X, priv.Y = curve.ScalarBaseMult(privKey.PrivateKey)
+
+ return priv, nil
+}
diff --git a/src/pkg/crypto/x509/sec1_test.go b/src/pkg/crypto/x509/sec1_test.go
new file mode 100644
index 000000000..7135699d2
--- /dev/null
+++ b/src/pkg/crypto/x509/sec1_test.go
@@ -0,0 +1,22 @@
+// 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 x509
+
+import (
+ "encoding/hex"
+ "testing"
+)
+
+// Generated using:
+// openssl ecparam -genkey -name secp384r1 -outform PEM
+var ecPrivateKeyHex = `3081a40201010430bdb9839c08ee793d1157886a7a758a3c8b2a17a4df48f17ace57c72c56b4723cf21dcda21d4e1ad57ff034f19fcfd98ea00706052b81040022a16403620004feea808b5ee2429cfcce13c32160e1c960990bd050bb0fdf7222f3decd0a55008e32a6aa3c9062051c4cba92a7a3b178b24567412d43cdd2f882fa5addddd726fe3e208d2c26d733a773a597abb749714df7256ead5105fa6e7b3650de236b50`
+
+func TestParseECPrivateKey(t *testing.T) {
+ derBytes, _ := hex.DecodeString(ecPrivateKeyHex)
+ _, err := ParseECPrivateKey(derBytes)
+ if err != nil {
+ t.Errorf("failed to decode EC private key: %s", err)
+ }
+}
diff --git a/src/pkg/crypto/x509/verify.go b/src/pkg/crypto/x509/verify.go
index 307c5ef03..b29ddbc80 100644
--- a/src/pkg/crypto/x509/verify.go
+++ b/src/pkg/crypto/x509/verify.go
@@ -5,6 +5,7 @@
package x509
import (
+ "net"
"runtime"
"strings"
"time"
@@ -27,6 +28,9 @@ const (
// TooManyIntermediates results when a path length constraint is
// violated.
TooManyIntermediates
+ // IncompatibleUsage results when the certificate's key usage indicates
+ // that it may only be used for a different purpose.
+ IncompatibleUsage
)
// CertificateInvalidError results when an odd error occurs. Users of this
@@ -39,13 +43,15 @@ type CertificateInvalidError struct {
func (e CertificateInvalidError) Error() string {
switch e.Reason {
case NotAuthorizedToSign:
- return "x509: certificate is not authorized to sign other other certificates"
+ return "x509: certificate is not authorized to sign other certificates"
case Expired:
return "x509: certificate has expired or is not yet valid"
case CANotAuthorizedForThisName:
return "x509: a root or intermediate certificate is not authorized to sign in this domain"
case TooManyIntermediates:
return "x509: too many intermediates for path length constraint"
+ case IncompatibleUsage:
+ return "x509: certificate specifies an incompatible key usage"
}
return "x509: unknown error"
}
@@ -58,14 +64,28 @@ type HostnameError struct {
}
func (h HostnameError) Error() string {
- var valid string
c := h.Certificate
- if len(c.DNSNames) > 0 {
- valid = strings.Join(c.DNSNames, ", ")
+
+ var valid string
+ if ip := net.ParseIP(h.Host); ip != nil {
+ // Trying to validate an IP
+ if len(c.IPAddresses) == 0 {
+ return "x509: cannot validate certificate for " + h.Host + " because it doesn't contain any IP SANs"
+ }
+ for _, san := range c.IPAddresses {
+ if len(valid) > 0 {
+ valid += ", "
+ }
+ valid += san.String()
+ }
} else {
- valid = c.Subject.CommonName
+ if len(c.DNSNames) > 0 {
+ valid = strings.Join(c.DNSNames, ", ")
+ } else {
+ valid = c.Subject.CommonName
+ }
}
- return "certificate is valid for " + valid + ", not " + h.Host
+ return "x509: certificate is valid for " + valid + ", not " + h.Host
}
// UnknownAuthorityError results when the certificate issuer is unknown
@@ -77,6 +97,14 @@ func (e UnknownAuthorityError) Error() string {
return "x509: certificate signed by unknown authority"
}
+// SystemRootsError results when we fail to load the system root certificates.
+type SystemRootsError struct {
+}
+
+func (e SystemRootsError) Error() string {
+ return "x509: failed to load system roots and no roots provided"
+}
+
// VerifyOptions contains parameters for Certificate.Verify. It's a structure
// because other PKIX verification APIs have ended up needing many options.
type VerifyOptions struct {
@@ -84,6 +112,11 @@ type VerifyOptions struct {
Intermediates *CertPool
Roots *CertPool // if nil, the system roots are used
CurrentTime time.Time // if zero, the current time is used
+ // KeyUsage specifies which Extended Key Usage values are acceptable.
+ // An empty list means ExtKeyUsageServerAuth. Key usage is considered a
+ // constraint down the chain which mirrors Windows CryptoAPI behaviour,
+ // but not the spec. To accept any key usage, include ExtKeyUsageAny.
+ KeyUsages []ExtKeyUsage
}
const (
@@ -160,6 +193,9 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e
if opts.Roots == nil {
opts.Roots = systemRootsPool()
+ if opts.Roots == nil {
+ return nil, SystemRootsError{}
+ }
}
err = c.isValid(leafCertificate, nil, &opts)
@@ -174,7 +210,35 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e
}
}
- return c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts)
+ candidateChains, err := c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts)
+ if err != nil {
+ return
+ }
+
+ keyUsages := opts.KeyUsages
+ if len(keyUsages) == 0 {
+ keyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth}
+ }
+
+ // If any key usage is acceptable then we're done.
+ for _, usage := range keyUsages {
+ if usage == ExtKeyUsageAny {
+ chains = candidateChains
+ return
+ }
+ }
+
+ for _, candidate := range candidateChains {
+ if checkChainForKeyUsage(candidate, keyUsages) {
+ chains = append(chains, candidate)
+ }
+ }
+
+ if len(chains) == 0 {
+ err = CertificateInvalidError{c, IncompatibleUsage}
+ }
+
+ return
}
func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate {
@@ -285,6 +349,22 @@ func toLowerCaseASCII(in string) string {
// VerifyHostname returns nil if c is a valid certificate for the named host.
// Otherwise it returns an error describing the mismatch.
func (c *Certificate) VerifyHostname(h string) error {
+ // IP addresses may be written in [ ].
+ candidateIP := h
+ if len(h) >= 3 && h[0] == '[' && h[len(h)-1] == ']' {
+ candidateIP = h[1 : len(h)-1]
+ }
+ if ip := net.ParseIP(candidateIP); ip != nil {
+ // We only match IP addresses against IP SANs.
+ // https://tools.ietf.org/html/rfc6125#appendix-B.2
+ for _, candidate := range c.IPAddresses {
+ if ip.Equal(candidate) {
+ return nil
+ }
+ }
+ return HostnameError{c, candidateIP}
+ }
+
lowered := toLowerCaseASCII(h)
if len(c.DNSNames) > 0 {
@@ -300,3 +380,64 @@ func (c *Certificate) VerifyHostname(h string) error {
return HostnameError{c, h}
}
+
+func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool {
+ usages := make([]ExtKeyUsage, len(keyUsages))
+ copy(usages, keyUsages)
+
+ if len(chain) == 0 {
+ return false
+ }
+
+ usagesRemaining := len(usages)
+
+ // We walk down the list and cross out any usages that aren't supported
+ // by each certificate. If we cross out all the usages, then the chain
+ // is unacceptable.
+
+ for i := len(chain) - 1; i >= 0; i-- {
+ cert := chain[i]
+ if len(cert.ExtKeyUsage) == 0 && len(cert.UnknownExtKeyUsage) == 0 {
+ // The certificate doesn't have any extended key usage specified.
+ continue
+ }
+
+ for _, usage := range cert.ExtKeyUsage {
+ if usage == ExtKeyUsageAny {
+ // The certificate is explicitly good for any usage.
+ continue
+ }
+ }
+
+ const invalidUsage ExtKeyUsage = -1
+
+ NextRequestedUsage:
+ for i, requestedUsage := range usages {
+ if requestedUsage == invalidUsage {
+ continue
+ }
+
+ for _, usage := range cert.ExtKeyUsage {
+ if requestedUsage == usage {
+ continue NextRequestedUsage
+ } else if requestedUsage == ExtKeyUsageServerAuth &&
+ (usage == ExtKeyUsageNetscapeServerGatedCrypto ||
+ usage == ExtKeyUsageMicrosoftServerGatedCrypto) {
+ // In order to support COMODO
+ // certificate chains, we have to
+ // accept Netscape or Microsoft SGC
+ // usages as equal to ServerAuth.
+ continue NextRequestedUsage
+ }
+ }
+
+ usages[i] = invalidUsage
+ usagesRemaining--
+ if usagesRemaining == 0 {
+ return false
+ }
+ }
+ }
+
+ return true
+}
diff --git a/src/pkg/crypto/x509/verify_test.go b/src/pkg/crypto/x509/verify_test.go
index 7b171b291..5103ed814 100644
--- a/src/pkg/crypto/x509/verify_test.go
+++ b/src/pkg/crypto/x509/verify_test.go
@@ -15,12 +15,14 @@ import (
)
type verifyTest struct {
- leaf string
- intermediates []string
- roots []string
- currentTime int64
- dnsName string
- systemSkip bool
+ leaf string
+ intermediates []string
+ roots []string
+ currentTime int64
+ dnsName string
+ systemSkip bool
+ keyUsages []ExtKeyUsage
+ testSystemRootsError bool
errorCallback func(*testing.T, int, error) bool
expectedChains [][]string
@@ -28,6 +30,17 @@ type verifyTest struct {
var verifyTests = []verifyTest{
{
+ leaf: googleLeaf,
+ intermediates: []string{thawteIntermediate},
+ currentTime: 1302726541,
+ dnsName: "www.google.com",
+ testSystemRootsError: true,
+
+ // Without any roots specified we should get a system roots
+ // error.
+ errorCallback: expectSystemRootsError,
+ },
+ {
leaf: googleLeaf,
intermediates: []string{thawteIntermediate},
roots: []string{verisignRoot},
@@ -113,6 +126,51 @@ var verifyTests = []verifyTest{
{"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority", "StartCom Certification Authority"},
},
},
+ {
+ // The default configuration should reject an S/MIME chain.
+ leaf: smimeLeaf,
+ roots: []string{smimeIntermediate},
+ currentTime: 1339436154,
+
+ // Key usage not implemented for Windows yet.
+ systemSkip: true,
+ errorCallback: expectUsageError,
+ },
+ {
+ leaf: smimeLeaf,
+ roots: []string{smimeIntermediate},
+ currentTime: 1339436154,
+ keyUsages: []ExtKeyUsage{ExtKeyUsageServerAuth},
+
+ // Key usage not implemented for Windows yet.
+ systemSkip: true,
+ errorCallback: expectUsageError,
+ },
+ {
+ leaf: smimeLeaf,
+ roots: []string{smimeIntermediate},
+ currentTime: 1339436154,
+ keyUsages: []ExtKeyUsage{ExtKeyUsageEmailProtection},
+
+ // Key usage not implemented for Windows yet.
+ systemSkip: true,
+ expectedChains: [][]string{
+ {"Ryan Hurst", "GlobalSign PersonalSign 2 CA - G2"},
+ },
+ },
+ {
+ leaf: megaLeaf,
+ intermediates: []string{comodoIntermediate1},
+ roots: []string{comodoRoot},
+ currentTime: 1360431182,
+
+ // CryptoAPI can find alternative validation paths so we don't
+ // perform this test with system validation.
+ systemSkip: true,
+ expectedChains: [][]string{
+ {"mega.co.nz", "EssentialSSL CA", "COMODO Certification Authority"},
+ },
+ },
}
func expectHostnameError(t *testing.T, i int, err error) (ok bool) {
@@ -131,6 +189,14 @@ func expectExpired(t *testing.T, i int, err error) (ok bool) {
return true
}
+func expectUsageError(t *testing.T, i int, err error) (ok bool) {
+ if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != IncompatibleUsage {
+ t.Errorf("#%d: error was not IncompatibleUsage: %s", i, err)
+ return false
+ }
+ return true
+}
+
func expectAuthorityUnknown(t *testing.T, i int, err error) (ok bool) {
if _, ok := err.(UnknownAuthorityError); !ok {
t.Errorf("#%d: error was not UnknownAuthorityError: %s", i, err)
@@ -139,6 +205,14 @@ func expectAuthorityUnknown(t *testing.T, i int, err error) (ok bool) {
return true
}
+func expectSystemRootsError(t *testing.T, i int, err error) bool {
+ if _, ok := err.(SystemRootsError); !ok {
+ t.Errorf("#%d: error was not SystemRootsError: %s", i, err)
+ return false
+ }
+ return true
+}
+
func certificateFromPEM(pemBytes string) (*Certificate, error) {
block, _ := pem.Decode([]byte(pemBytes))
if block == nil {
@@ -152,11 +226,15 @@ func testVerify(t *testing.T, useSystemRoots bool) {
if useSystemRoots && test.systemSkip {
continue
}
+ if runtime.GOOS == "windows" && test.testSystemRootsError {
+ continue
+ }
opts := VerifyOptions{
Intermediates: NewCertPool(),
DNSName: test.dnsName,
CurrentTime: time.Unix(test.currentTime, 0),
+ KeyUsages: test.keyUsages,
}
if !useSystemRoots {
@@ -184,8 +262,19 @@ func testVerify(t *testing.T, useSystemRoots bool) {
return
}
+ var oldSystemRoots *CertPool
+ if test.testSystemRootsError {
+ oldSystemRoots = systemRootsPool()
+ systemRoots = nil
+ opts.Roots = nil
+ }
+
chains, err := leaf.Verify(opts)
+ if test.testSystemRootsError {
+ systemRoots = oldSystemRoots
+ }
+
if test.errorCallback == nil && err != nil {
t.Errorf("#%d: unexpected error: %s", i, err)
}
@@ -233,8 +322,7 @@ func TestGoVerify(t *testing.T) {
func TestSystemVerify(t *testing.T) {
if runtime.GOOS != "windows" {
- t.Logf("skipping verify test using system APIs on %q", runtime.GOOS)
- return
+ t.Skipf("skipping verify test using system APIs on %q", runtime.GOOS)
}
testVerify(t, true)
@@ -433,3 +521,145 @@ O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V
um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh
NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14=
-----END CERTIFICATE-----`
+
+const smimeLeaf = `-----BEGIN CERTIFICATE-----
+MIIFBjCCA+6gAwIBAgISESFvrjT8XcJTEe6rBlPptILlMA0GCSqGSIb3DQEBBQUA
+MFQxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMSowKAYD
+VQQDEyFHbG9iYWxTaWduIFBlcnNvbmFsU2lnbiAyIENBIC0gRzIwHhcNMTIwMTIz
+MTYzNjU5WhcNMTUwMTIzMTYzNjU5WjCBlDELMAkGA1UEBhMCVVMxFjAUBgNVBAgT
+DU5ldyBIYW1zcGhpcmUxEzARBgNVBAcTClBvcnRzbW91dGgxGTAXBgNVBAoTEEds
+b2JhbFNpZ24sIEluYy4xEzARBgNVBAMTClJ5YW4gSHVyc3QxKDAmBgkqhkiG9w0B
+CQEWGXJ5YW4uaHVyc3RAZ2xvYmFsc2lnbi5jb20wggEiMA0GCSqGSIb3DQEBAQUA
+A4IBDwAwggEKAoIBAQC4ASSTvavmsFQAob60ukSSwOAL9nT/s99ltNUCAf5fPH5j
+NceMKxaQse2miOmRRIXaykcq1p/TbI70Ztce38r2mbOwqDHHPVi13GxJEyUXWgaR
+BteDMu5OGyWNG1kchVsGWpbstT0Z4v0md5m1BYFnxB20ebJyOR2lXDxsFK28nnKV
++5eMj76U8BpPQ4SCH7yTMG6y0XXsB3cCrBKr2o3TOYgEKv+oNnbaoMt3UxMt9nSf
+9jyIshjqfnT5Aew3CUNMatO55g5FXXdIukAweg1YSb1ls05qW3sW00T3d7dQs9/7
+NuxCg/A2elmVJSoy8+MLR8JSFEf/aMgjO/TyLg/jAgMBAAGjggGPMIIBizAOBgNV
+HQ8BAf8EBAMCBaAwTQYDVR0gBEYwRDBCBgorBgEEAaAyASgKMDQwMgYIKwYBBQUH
+AgEWJmh0dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9zaXRvcnkvMCQGA1Ud
+EQQdMBuBGXJ5YW4uaHVyc3RAZ2xvYmFsc2lnbi5jb20wCQYDVR0TBAIwADAdBgNV
+HSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwQwYDVR0fBDwwOjA4oDagNIYyaHR0
+cDovL2NybC5nbG9iYWxzaWduLmNvbS9ncy9nc3BlcnNvbmFsc2lnbjJnMi5jcmww
+VQYIKwYBBQUHAQEESTBHMEUGCCsGAQUFBzAChjlodHRwOi8vc2VjdXJlLmdsb2Jh
+bHNpZ24uY29tL2NhY2VydC9nc3BlcnNvbmFsc2lnbjJnMi5jcnQwHQYDVR0OBBYE
+FFWiECe0/L72eVYqcWYnLV6SSjzhMB8GA1UdIwQYMBaAFD8V0m18L+cxnkMKBqiU
+bCw7xe5lMA0GCSqGSIb3DQEBBQUAA4IBAQAhQi6hLPeudmf3IBF4IDzCvRI0FaYd
+BKfprSk/H0PDea4vpsLbWpA0t0SaijiJYtxKjlM4bPd+2chb7ejatDdyrZIzmDVy
+q4c30/xMninGKokpYA11/Ve+i2dvjulu65qasrtQRGybAuuZ67lrp/K3OMFgjV5N
+C3AHYLzvNU4Dwc4QQ1BaMOg6KzYSrKbABRZajfrpC9uiePsv7mDIXLx/toBPxWNl
+a5vJm5DrZdn7uHdvBCE6kMykbOLN5pmEK0UIlwKh6Qi5XD0pzlVkEZliFkBMJgub
+d/eF7xeg7TKPWC5xyOFp9SdMolJM7LTC3wnSO3frBAev+q/nGs9Xxyvs
+-----END CERTIFICATE-----`
+
+const smimeIntermediate = `-----BEGIN CERTIFICATE-----
+MIIEFjCCAv6gAwIBAgILBAAAAAABL07hL1IwDQYJKoZIhvcNAQEFBQAwVzELMAkG
+A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
+b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xMTA0MTMxMDAw
+MDBaFw0xOTA0MTMxMDAwMDBaMFQxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
+YWxTaWduIG52LXNhMSowKAYDVQQDEyFHbG9iYWxTaWduIFBlcnNvbmFsU2lnbiAy
+IENBIC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBa0H5Nez4
+En3dIlFpX7e5E0YndxQ74xOBbz7kdBd+DLX0LOQMjVPU3DAgKL9ujhH+ZhHkURbH
+3X/94TQSUL/z2JjsaQvS0NqyZXHhM5eeuquzOJRzEQ8+odETzHg2G0Erv7yjSeww
+gkwDWDJnYUDlOjYTDUEG6+i+8Mn425reo4I0E277wD542kmVWeW7+oHv5dZo9e1Q
+yWwiKTEP6BEQVVSBgThXMG4traSSDRUt3T1eQTZx5EObpiBEBO4OTqiBTJfg4vEI
+YgkXzKLpnfszTB6YMDpR9/QS6p3ANB3kfAb+t6udSO3WCst0DGrwHDLBFGDR4UeY
+T5KGGnI7cWL7AgMBAAGjgeUwgeIwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQI
+MAYBAf8CAQAwHQYDVR0OBBYEFD8V0m18L+cxnkMKBqiUbCw7xe5lMEcGA1UdIARA
+MD4wPAYEVR0gADA0MDIGCCsGAQUFBwIBFiZodHRwczovL3d3dy5nbG9iYWxzaWdu
+LmNvbS9yZXBvc2l0b3J5LzAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3JsLmds
+b2JhbHNpZ24ubmV0L3Jvb3QuY3JsMB8GA1UdIwQYMBaAFGB7ZhpFDZfKiVAvfQTN
+NKj//P1LMA0GCSqGSIb3DQEBBQUAA4IBAQBDc3nMpMxJMQMcYUCB3+C73UpvwDE8
+eCOr7t2F/uaQKKcyqqstqLZc6vPwI/rcE9oDHugY5QEjQzIBIEaTnN6P0vege2IX
+eCOr7t2F/uaQKKcyqqstqLZc6vPwI/rcE9oDHugY5QEjQzIBIEaTnN6P0vege2IX
+YEvTWbWwGdPytDFPYIl3/6OqNSXSnZ7DxPcdLJq2uyiga8PB/TTIIHYkdM2+1DE0
+7y3rH/7TjwDVD7SLu5/SdOfKskuMPTjOEvz3K161mymW06klVhubCIWOro/Gx1Q2
+2FQOZ7/2k4uYoOdBTSlb8kTAuzZNgIE0rB2BIYCTz/P6zZIKW0ogbRSH
+-----END CERTIFICATE-----`
+
+var megaLeaf = `-----BEGIN CERTIFICATE-----
+MIIFOjCCBCKgAwIBAgIQWYE8Dup170kZ+k11Lg51OjANBgkqhkiG9w0BAQUFADBy
+MQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYD
+VQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDEYMBYGA1UE
+AxMPRXNzZW50aWFsU1NMIENBMB4XDTEyMTIxNDAwMDAwMFoXDTE0MTIxNDIzNTk1
+OVowfzEhMB8GA1UECxMYRG9tYWluIENvbnRyb2wgVmFsaWRhdGVkMS4wLAYDVQQL
+EyVIb3N0ZWQgYnkgSW5zdHJhIENvcnBvcmF0aW9uIFB0eS4gTFREMRUwEwYDVQQL
+EwxFc3NlbnRpYWxTU0wxEzARBgNVBAMTCm1lZ2EuY28ubnowggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDcxMCClae8BQIaJHBUIVttlLvhbK4XhXPk3RQ3
+G5XA6tLZMBQ33l3F9knYJ0YErXtr8IdfYoulRQFmKFMJl9GtWyg4cGQi2Rcr5VN5
+S5dA1vu4oyJBxE9fPELcK6Yz1vqaf+n6za+mYTiQYKggVdS8/s8hmNuXP9Zk1pIn
++q0pGsf8NAcSHMJgLqPQrTDw+zae4V03DvcYfNKjuno88d2226ld7MAmQZ7uRNsI
+/CnkdelVs+akZsXf0szefSqMJlf08SY32t2jj4Ra7RApVYxOftD9nij/aLfuqOU6
+ow6IgIcIG2ZvXLZwK87c5fxL7UAsTTV+M1sVv8jA33V2oKLhAgMBAAGjggG9MIIB
+uTAfBgNVHSMEGDAWgBTay+qtWwhdzP/8JlTOSeVVxjj0+DAdBgNVHQ4EFgQUmP9l
+6zhyrZ06Qj4zogt+6LKFk4AwDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAw
+NAYDVR0lBC0wKwYIKwYBBQUHAwEGCCsGAQUFBwMCBgorBgEEAYI3CgMDBglghkgB
+hvhCBAEwTwYDVR0gBEgwRjA6BgsrBgEEAbIxAQICBzArMCkGCCsGAQUFBwIBFh1o
+dHRwczovL3NlY3VyZS5jb21vZG8uY29tL0NQUzAIBgZngQwBAgEwOwYDVR0fBDQw
+MjAwoC6gLIYqaHR0cDovL2NybC5jb21vZG9jYS5jb20vRXNzZW50aWFsU1NMQ0Eu
+Y3JsMG4GCCsGAQUFBwEBBGIwYDA4BggrBgEFBQcwAoYsaHR0cDovL2NydC5jb21v
+ZG9jYS5jb20vRXNzZW50aWFsU1NMQ0FfMi5jcnQwJAYIKwYBBQUHMAGGGGh0dHA6
+Ly9vY3NwLmNvbW9kb2NhLmNvbTAlBgNVHREEHjAcggptZWdhLmNvLm56gg53d3cu
+bWVnYS5jby5uejANBgkqhkiG9w0BAQUFAAOCAQEAcYhrsPSvDuwihMOh0ZmRpbOE
+Gw6LqKgLNTmaYUPQhzi2cyIjhUhNvugXQQlP5f0lp5j8cixmArafg1dTn4kQGgD3
+ivtuhBTgKO1VYB/VRoAt6Lmswg3YqyiS7JiLDZxjoV7KoS5xdiaINfHDUaBBY4ZH
+j2BUlPniNBjCqXe/HndUTVUewlxbVps9FyCmH+C4o9DWzdGBzDpCkcmo5nM+cp7q
+ZhTIFTvZfo3zGuBoyu8BzuopCJcFRm3cRiXkpI7iOMUIixO1szkJS6WpL1sKdT73
+UXp08U0LBqoqG130FbzEJBBV3ixbvY6BWMHoCWuaoF12KJnC5kHt2RoWAAgMXA==
+-----END CERTIFICATE-----`
+
+var comodoIntermediate1 = `-----BEGIN CERTIFICATE-----
+MIIFAzCCA+ugAwIBAgIQGLLLuqME8aAPwfLzJkYqSjANBgkqhkiG9w0BAQUFADCB
+gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV
+BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw
+MDBaFw0xOTEyMzEyMzU5NTlaMHIxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVh
+dGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9E
+TyBDQSBMaW1pdGVkMRgwFgYDVQQDEw9Fc3NlbnRpYWxTU0wgQ0EwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCt8AiwcsargxIxF3CJhakgEtSYau2A1NHf
+5I5ZLdOWIY120j8YC0YZYwvHIPPlC92AGvFaoL0dds23Izp0XmEbdaqb1IX04XiR
+0y3hr/yYLgbSeT1awB8hLRyuIVPGOqchfr7tZ291HRqfalsGs2rjsQuqag7nbWzD
+ypWMN84hHzWQfdvaGlyoiBSyD8gSIF/F03/o4Tjg27z5H6Gq1huQByH6RSRQXScq
+oChBRVt9vKCiL6qbfltTxfEFFld+Edc7tNkBdtzffRDPUanlOPJ7FAB1WfnwWdsX
+Pvev5gItpHnBXaIcw5rIp6gLSApqLn8tl2X2xQScRMiZln5+pN0vAgMBAAGjggGD
+MIIBfzAfBgNVHSMEGDAWgBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAdBgNVHQ4EFgQU
+2svqrVsIXcz//CZUzknlVcY49PgwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQI
+MAYBAf8CAQAwIAYDVR0lBBkwFwYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMD4GA1Ud
+IAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwczovL3NlY3VyZS5jb21v
+ZG8uY29tL0NQUzBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9kb2Nh
+LmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDBsBggrBgEFBQcB
+AQRgMF4wNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NvbW9k
+b1VUTlNHQ0NBLmNydDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2Eu
+Y29tMA0GCSqGSIb3DQEBBQUAA4IBAQAtlzR6QDLqcJcvgTtLeRJ3rvuq1xqo2l/z
+odueTZbLN3qo6u6bldudu+Ennv1F7Q5Slqz0J790qpL0pcRDAB8OtXj5isWMcL2a
+ejGjKdBZa0wztSz4iw+SY1dWrCRnilsvKcKxudokxeRiDn55w/65g+onO7wdQ7Vu
+F6r7yJiIatnyfKH2cboZT7g440LX8NqxwCPf3dfxp+0Jj1agq8MLy6SSgIGSH6lv
++Wwz3D5XxqfyH8wqfOQsTEZf6/Nh9yvENZ+NWPU6g0QO2JOsTGvMd/QDzczc4BxL
+XSXaPV7Od4rhPsbXlM1wSTz/Dr0ISKvlUhQVnQ6cGodWaK2cCQBk
+-----END CERTIFICATE-----`
+
+var comodoRoot = `-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB
+gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV
+BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw
+MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl
+YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P
+RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3
+UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI
+2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8
+Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp
++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+
+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O
+nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW
+/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g
+PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u
+QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY
+SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv
+IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
+RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4
+zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd
+BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB
+ZQ==
+-----END CERTIFICATE-----`
diff --git a/src/pkg/crypto/x509/x509.go b/src/pkg/crypto/x509/x509.go
index c4d85e67f..b802bf4eb 100644
--- a/src/pkg/crypto/x509/x509.go
+++ b/src/pkg/crypto/x509/x509.go
@@ -9,6 +9,8 @@ import (
"bytes"
"crypto"
"crypto/dsa"
+ "crypto/ecdsa"
+ "crypto/elliptic"
"crypto/rsa"
"crypto/sha1"
"crypto/x509/pkix"
@@ -17,6 +19,8 @@ import (
"errors"
"io"
"math/big"
+ "net"
+ "strconv"
"time"
)
@@ -106,6 +110,8 @@ type dsaSignature struct {
R, S *big.Int
}
+type ecdsaSignature dsaSignature
+
type validity struct {
NotBefore, NotAfter time.Time
}
@@ -133,6 +139,10 @@ const (
SHA512WithRSA
DSAWithSHA1
DSAWithSHA256
+ ECDSAWithSHA1
+ ECDSAWithSHA256
+ ECDSAWithSHA384
+ ECDSAWithSHA512
)
type PublicKeyAlgorithm int
@@ -141,14 +151,15 @@ const (
UnknownPublicKeyAlgorithm PublicKeyAlgorithm = iota
RSA
DSA
+ ECDSA
)
// OIDs for signature algorithms
//
// pkcs-1 OBJECT IDENTIFIER ::= {
// iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
-//
-//
+//
+//
// RFC 3279 2.2.1 RSA Signature Algorithms
//
// md2WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 2 }
@@ -156,13 +167,19 @@ const (
// md5WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 4 }
//
// sha-1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 }
-//
+//
// dsaWithSha1 OBJECT IDENTIFIER ::= {
-// iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 3 }
+// iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 3 }
+//
+// RFC 3279 2.2.3 ECDSA Signature Algorithm
+//
+// ecdsa-with-SHA1 OBJECT IDENTIFIER ::= {
+// iso(1) member-body(2) us(840) ansi-x962(10045)
+// signatures(4) ecdsa-with-SHA1(1)}
//
//
// RFC 4055 5 PKCS #1 Version 1.5
-//
+//
// sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 }
//
// sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 }
@@ -176,15 +193,30 @@ const (
// joint-iso-ccitt(2) country(16) us(840) organization(1) gov(101)
// csor(3) algorithms(4) id-dsa-with-sha2(3) 2}
//
+// RFC 5758 3.2 ECDSA Signature Algorithm
+//
+// ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 }
+//
+// ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 3 }
+//
+// ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 4 }
+
var (
- oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2}
- oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4}
- oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}
- oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
- 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}
+ oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2}
+ oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4}
+ oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}
+ oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
+ 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}
+ 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}
+ oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}
)
func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) SignatureAlgorithm {
@@ -205,6 +237,14 @@ func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) SignatureAlgorithm
return DSAWithSHA1
case oid.Equal(oidSignatureDSAWithSHA256):
return DSAWithSHA256
+ case oid.Equal(oidSignatureECDSAWithSHA1):
+ return ECDSAWithSHA1
+ case oid.Equal(oidSignatureECDSAWithSHA256):
+ return ECDSAWithSHA256
+ case oid.Equal(oidSignatureECDSAWithSHA384):
+ return ECDSAWithSHA384
+ case oid.Equal(oidSignatureECDSAWithSHA512):
+ return ECDSAWithSHA512
}
return UnknownSignatureAlgorithm
}
@@ -218,21 +258,81 @@ func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) SignatureAlgorithm
//
// id-dsa OBJECT IDENTIFIER ::== { iso(1) member-body(2) us(840)
// x9-57(10040) x9cm(4) 1 }
+//
+// RFC 5480, 2.1.1 Unrestricted Algorithm Identifier and Parameters
+//
+// id-ecPublicKey OBJECT IDENTIFIER ::= {
+// iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 }
var (
- oidPublicKeyRsa = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
- oidPublicKeyDsa = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 1}
+ oidPublicKeyRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
+ oidPublicKeyDSA = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 1}
+ oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}
)
func getPublicKeyAlgorithmFromOID(oid asn1.ObjectIdentifier) PublicKeyAlgorithm {
switch {
- case oid.Equal(oidPublicKeyRsa):
+ case oid.Equal(oidPublicKeyRSA):
return RSA
- case oid.Equal(oidPublicKeyDsa):
+ case oid.Equal(oidPublicKeyDSA):
return DSA
+ case oid.Equal(oidPublicKeyECDSA):
+ return ECDSA
}
return UnknownPublicKeyAlgorithm
}
+// RFC 5480, 2.1.1.1. Named Curve
+//
+// secp224r1 OBJECT IDENTIFIER ::= {
+// iso(1) identified-organization(3) certicom(132) curve(0) 33 }
+//
+// secp256r1 OBJECT IDENTIFIER ::= {
+// iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3)
+// prime(1) 7 }
+//
+// secp384r1 OBJECT IDENTIFIER ::= {
+// iso(1) identified-organization(3) certicom(132) curve(0) 34 }
+//
+// secp521r1 OBJECT IDENTIFIER ::= {
+// iso(1) identified-organization(3) certicom(132) curve(0) 35 }
+//
+// NB: secp256r1 is equivalent to prime256v1
+var (
+ oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33}
+ oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7}
+ oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34}
+ oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35}
+)
+
+func namedCurveFromOID(oid asn1.ObjectIdentifier) elliptic.Curve {
+ switch {
+ case oid.Equal(oidNamedCurveP224):
+ return elliptic.P224()
+ case oid.Equal(oidNamedCurveP256):
+ return elliptic.P256()
+ case oid.Equal(oidNamedCurveP384):
+ return elliptic.P384()
+ case oid.Equal(oidNamedCurveP521):
+ return elliptic.P521()
+ }
+ return nil
+}
+
+func oidFromNamedCurve(curve elliptic.Curve) (asn1.ObjectIdentifier, bool) {
+ switch curve {
+ case elliptic.P224():
+ return oidNamedCurveP224, true
+ case elliptic.P256():
+ return oidNamedCurveP256, true
+ case elliptic.P384():
+ return oidNamedCurveP384, true
+ case elliptic.P521():
+ return oidNamedCurveP521, true
+ }
+
+ return nil, false
+}
+
// KeyUsage represents the set of actions that are valid for a given key. It's
// a bitmap of the KeyUsage* constants.
type KeyUsage int
@@ -262,13 +362,18 @@ const (
// id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 }
// id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 }
var (
- oidExtKeyUsageAny = asn1.ObjectIdentifier{2, 5, 29, 37, 0}
- oidExtKeyUsageServerAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 1}
- oidExtKeyUsageClientAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 2}
- oidExtKeyUsageCodeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 3}
- oidExtKeyUsageEmailProtection = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 4}
- oidExtKeyUsageTimeStamping = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 8}
- oidExtKeyUsageOCSPSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 9}
+ oidExtKeyUsageAny = asn1.ObjectIdentifier{2, 5, 29, 37, 0}
+ oidExtKeyUsageServerAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 1}
+ oidExtKeyUsageClientAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 2}
+ oidExtKeyUsageCodeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 3}
+ oidExtKeyUsageEmailProtection = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 4}
+ oidExtKeyUsageIPSECEndSystem = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 5}
+ oidExtKeyUsageIPSECTunnel = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 6}
+ oidExtKeyUsageIPSECUser = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 7}
+ oidExtKeyUsageTimeStamping = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 8}
+ oidExtKeyUsageOCSPSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 9}
+ oidExtKeyUsageMicrosoftServerGatedCrypto = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 3}
+ oidExtKeyUsageNetscapeServerGatedCrypto = asn1.ObjectIdentifier{2, 16, 840, 1, 113730, 4, 1}
)
// ExtKeyUsage represents an extended set of actions that are valid for a given key.
@@ -281,10 +386,52 @@ const (
ExtKeyUsageClientAuth
ExtKeyUsageCodeSigning
ExtKeyUsageEmailProtection
+ ExtKeyUsageIPSECEndSystem
+ ExtKeyUsageIPSECTunnel
+ ExtKeyUsageIPSECUser
ExtKeyUsageTimeStamping
ExtKeyUsageOCSPSigning
+ ExtKeyUsageMicrosoftServerGatedCrypto
+ ExtKeyUsageNetscapeServerGatedCrypto
)
+// extKeyUsageOIDs contains the mapping between an ExtKeyUsage and its OID.
+var extKeyUsageOIDs = []struct {
+ extKeyUsage ExtKeyUsage
+ oid asn1.ObjectIdentifier
+}{
+ {ExtKeyUsageAny, oidExtKeyUsageAny},
+ {ExtKeyUsageServerAuth, oidExtKeyUsageServerAuth},
+ {ExtKeyUsageClientAuth, oidExtKeyUsageClientAuth},
+ {ExtKeyUsageCodeSigning, oidExtKeyUsageCodeSigning},
+ {ExtKeyUsageEmailProtection, oidExtKeyUsageEmailProtection},
+ {ExtKeyUsageIPSECEndSystem, oidExtKeyUsageIPSECEndSystem},
+ {ExtKeyUsageIPSECTunnel, oidExtKeyUsageIPSECTunnel},
+ {ExtKeyUsageIPSECUser, oidExtKeyUsageIPSECUser},
+ {ExtKeyUsageTimeStamping, oidExtKeyUsageTimeStamping},
+ {ExtKeyUsageOCSPSigning, oidExtKeyUsageOCSPSigning},
+ {ExtKeyUsageMicrosoftServerGatedCrypto, oidExtKeyUsageMicrosoftServerGatedCrypto},
+ {ExtKeyUsageNetscapeServerGatedCrypto, oidExtKeyUsageNetscapeServerGatedCrypto},
+}
+
+func extKeyUsageFromOID(oid asn1.ObjectIdentifier) (eku ExtKeyUsage, ok bool) {
+ for _, pair := range extKeyUsageOIDs {
+ if oid.Equal(pair.oid) {
+ return pair.extKeyUsage, true
+ }
+ }
+ return
+}
+
+func oidFromExtKeyUsage(eku ExtKeyUsage) (oid asn1.ObjectIdentifier, ok bool) {
+ for _, pair := range extKeyUsageOIDs {
+ if eku == pair.extKeyUsage {
+ return pair.oid, true
+ }
+ }
+ return
+}
+
// A Certificate represents an X.509 certificate.
type Certificate struct {
Raw []byte // Complete ASN.1 DER content (certificate, signature algorithm and signature).
@@ -319,6 +466,7 @@ type Certificate struct {
// Subject Alternate Name values
DNSNames []string
EmailAddresses []string
+ IPAddresses []net.IP
// Name constraints
PermittedDNSDomainsCritical bool // if true then the name constraints are marked critical.
@@ -344,6 +492,55 @@ func (c *Certificate) Equal(other *Certificate) bool {
return bytes.Equal(c.Raw, other.Raw)
}
+// Entrust have a broken root certificate (CN=Entrust.net Certification
+// Authority (2048)) which isn't marked as a CA certificate and is thus invalid
+// according to PKIX.
+// We recognise this certificate by its SubjectPublicKeyInfo and exempt it
+// from the Basic Constraints requirement.
+// See http://www.entrust.net/knowledge-base/technote.cfm?tn=7869
+//
+// TODO(agl): remove this hack once their reissued root is sufficiently
+// widespread.
+var entrustBrokenSPKI = []byte{
+ 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00,
+ 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01,
+ 0x00, 0x97, 0xa3, 0x2d, 0x3c, 0x9e, 0xde, 0x05,
+ 0xda, 0x13, 0xc2, 0x11, 0x8d, 0x9d, 0x8e, 0xe3,
+ 0x7f, 0xc7, 0x4b, 0x7e, 0x5a, 0x9f, 0xb3, 0xff,
+ 0x62, 0xab, 0x73, 0xc8, 0x28, 0x6b, 0xba, 0x10,
+ 0x64, 0x82, 0x87, 0x13, 0xcd, 0x57, 0x18, 0xff,
+ 0x28, 0xce, 0xc0, 0xe6, 0x0e, 0x06, 0x91, 0x50,
+ 0x29, 0x83, 0xd1, 0xf2, 0xc3, 0x2a, 0xdb, 0xd8,
+ 0xdb, 0x4e, 0x04, 0xcc, 0x00, 0xeb, 0x8b, 0xb6,
+ 0x96, 0xdc, 0xbc, 0xaa, 0xfa, 0x52, 0x77, 0x04,
+ 0xc1, 0xdb, 0x19, 0xe4, 0xae, 0x9c, 0xfd, 0x3c,
+ 0x8b, 0x03, 0xef, 0x4d, 0xbc, 0x1a, 0x03, 0x65,
+ 0xf9, 0xc1, 0xb1, 0x3f, 0x72, 0x86, 0xf2, 0x38,
+ 0xaa, 0x19, 0xae, 0x10, 0x88, 0x78, 0x28, 0xda,
+ 0x75, 0xc3, 0x3d, 0x02, 0x82, 0x02, 0x9c, 0xb9,
+ 0xc1, 0x65, 0x77, 0x76, 0x24, 0x4c, 0x98, 0xf7,
+ 0x6d, 0x31, 0x38, 0xfb, 0xdb, 0xfe, 0xdb, 0x37,
+ 0x02, 0x76, 0xa1, 0x18, 0x97, 0xa6, 0xcc, 0xde,
+ 0x20, 0x09, 0x49, 0x36, 0x24, 0x69, 0x42, 0xf6,
+ 0xe4, 0x37, 0x62, 0xf1, 0x59, 0x6d, 0xa9, 0x3c,
+ 0xed, 0x34, 0x9c, 0xa3, 0x8e, 0xdb, 0xdc, 0x3a,
+ 0xd7, 0xf7, 0x0a, 0x6f, 0xef, 0x2e, 0xd8, 0xd5,
+ 0x93, 0x5a, 0x7a, 0xed, 0x08, 0x49, 0x68, 0xe2,
+ 0x41, 0xe3, 0x5a, 0x90, 0xc1, 0x86, 0x55, 0xfc,
+ 0x51, 0x43, 0x9d, 0xe0, 0xb2, 0xc4, 0x67, 0xb4,
+ 0xcb, 0x32, 0x31, 0x25, 0xf0, 0x54, 0x9f, 0x4b,
+ 0xd1, 0x6f, 0xdb, 0xd4, 0xdd, 0xfc, 0xaf, 0x5e,
+ 0x6c, 0x78, 0x90, 0x95, 0xde, 0xca, 0x3a, 0x48,
+ 0xb9, 0x79, 0x3c, 0x9b, 0x19, 0xd6, 0x75, 0x05,
+ 0xa0, 0xf9, 0x88, 0xd7, 0xc1, 0xe8, 0xa5, 0x09,
+ 0xe4, 0x1a, 0x15, 0xdc, 0x87, 0x23, 0xaa, 0xb2,
+ 0x75, 0x8c, 0x63, 0x25, 0x87, 0xd8, 0xf8, 0x3d,
+ 0xa6, 0xc2, 0xcc, 0x66, 0xff, 0xa5, 0x66, 0x68,
+ 0x55, 0x02, 0x03, 0x01, 0x00, 0x01,
+}
+
// CheckSignatureFrom verifies that the signature on c is a valid signature
// from parent.
func (c *Certificate) CheckSignatureFrom(parent *Certificate) (err error) {
@@ -352,8 +549,10 @@ func (c *Certificate) CheckSignatureFrom(parent *Certificate) (err error) {
// certificate, or the extension is present but the cA boolean is not
// asserted, then the certified public key MUST NOT be used to verify
// certificate signatures."
- if parent.Version == 3 && !parent.BasicConstraintsValid ||
- parent.BasicConstraintsValid && !parent.IsCA {
+ // (except for Entrust, see comment above entrustBrokenSPKI)
+ if (parent.Version == 3 && !parent.BasicConstraintsValid ||
+ parent.BasicConstraintsValid && !parent.IsCA) &&
+ !bytes.Equal(c.RawSubjectPublicKeyInfo, entrustBrokenSPKI) {
return ConstraintViolationError{}
}
@@ -376,13 +575,13 @@ func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature
var hashType crypto.Hash
switch algo {
- case SHA1WithRSA, DSAWithSHA1:
+ case SHA1WithRSA, DSAWithSHA1, ECDSAWithSHA1:
hashType = crypto.SHA1
- case SHA256WithRSA, DSAWithSHA256:
+ case SHA256WithRSA, DSAWithSHA256, ECDSAWithSHA256:
hashType = crypto.SHA256
- case SHA384WithRSA:
+ case SHA384WithRSA, ECDSAWithSHA384:
hashType = crypto.SHA384
- case SHA512WithRSA:
+ case SHA512WithRSA, ECDSAWithSHA512:
hashType = crypto.SHA512
default:
return ErrUnsupportedAlgorithm
@@ -411,6 +610,18 @@ func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature
return errors.New("DSA verification failure")
}
return
+ case *ecdsa.PublicKey:
+ ecdsaSig := new(ecdsaSignature)
+ if _, err := asn1.Unmarshal(signature, ecdsaSig); err != nil {
+ return err
+ }
+ if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
+ return errors.New("crypto/x509: ECDSA signature contained zero or negative values")
+ }
+ if !ecdsa.Verify(pub, digest, ecdsaSig.R, ecdsaSig.S) {
+ return errors.New("crypto/x509: ECDSA verification failure")
+ }
+ return
}
return ErrUnsupportedAlgorithm
}
@@ -446,8 +657,6 @@ type nameConstraints struct {
type generalSubtree struct {
Name string `asn1:"tag:2,optional,ia5"`
- Min int `asn1:"optional,tag:0"`
- Max int `asn1:"optional,tag:1"`
}
func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{}, error) {
@@ -460,6 +669,13 @@ func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{
return nil, err
}
+ if p.N.Sign() <= 0 {
+ return nil, errors.New("x509: RSA modulus is not a positive number")
+ }
+ if p.E <= 0 {
+ return nil, errors.New("x509: RSA public exponent is not a positive number")
+ }
+
pub := &rsa.PublicKey{
E: p.E,
N: p.N,
@@ -489,6 +705,27 @@ func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{
Y: p,
}
return pub, nil
+ case ECDSA:
+ paramsData := keyData.Algorithm.Parameters.FullBytes
+ namedCurveOID := new(asn1.ObjectIdentifier)
+ _, err := asn1.Unmarshal(paramsData, namedCurveOID)
+ if err != nil {
+ return nil, err
+ }
+ namedCurve := namedCurveFromOID(*namedCurveOID)
+ if namedCurve == nil {
+ return nil, errors.New("crypto/x509: unsupported elliptic curve")
+ }
+ x, y := elliptic.Unmarshal(namedCurve, asn1Data)
+ if x == nil {
+ return nil, errors.New("crypto/x509: failed to unmarshal elliptic curve point")
+ }
+ pub := &ecdsa.PublicKey{
+ Curve: namedCurve,
+ X: x,
+ Y: y,
+ }
+ return pub, nil
default:
return nil, nil
}
@@ -607,6 +844,13 @@ func parseCertificate(in *certificate) (*Certificate, error) {
case 2:
out.DNSNames = append(out.DNSNames, string(v.Bytes))
parsedName = true
+ case 7:
+ switch len(v.Bytes) {
+ case net.IPv4len, net.IPv6len:
+ out.IPAddresses = append(out.IPAddresses, v.Bytes)
+ default:
+ return nil, errors.New("x509: certificate contained IP address of length " + strconv.Itoa(len(v.Bytes)))
+ }
}
}
@@ -643,7 +887,7 @@ func parseCertificate(in *certificate) (*Certificate, error) {
}
for _, subtree := range constraints.Permitted {
- if subtree.Min > 0 || subtree.Max > 0 || len(subtree.Name) == 0 {
+ if len(subtree.Name) == 0 {
if e.Critical {
return out, UnhandledCriticalExtension{}
}
@@ -679,22 +923,9 @@ func parseCertificate(in *certificate) (*Certificate, error) {
}
for _, u := range keyUsage {
- switch {
- case u.Equal(oidExtKeyUsageAny):
- out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageAny)
- case u.Equal(oidExtKeyUsageServerAuth):
- out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageServerAuth)
- case u.Equal(oidExtKeyUsageClientAuth):
- out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageClientAuth)
- case u.Equal(oidExtKeyUsageCodeSigning):
- out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageCodeSigning)
- case u.Equal(oidExtKeyUsageEmailProtection):
- out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageEmailProtection)
- case u.Equal(oidExtKeyUsageTimeStamping):
- out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageTimeStamping)
- case u.Equal(oidExtKeyUsageOCSPSigning):
- out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageOCSPSigning)
- default:
+ if extKeyUsage, ok := extKeyUsageFromOID(u); ok {
+ out.ExtKeyUsage = append(out.ExtKeyUsage, extKeyUsage)
+ } else {
out.UnknownExtKeyUsage = append(out.UnknownExtKeyUsage, u)
}
}
@@ -783,6 +1014,7 @@ func reverseBitsInAByte(in byte) byte {
var (
oidExtensionSubjectKeyId = []int{2, 5, 29, 14}
oidExtensionKeyUsage = []int{2, 5, 29, 15}
+ oidExtensionExtendedKeyUsage = []int{2, 5, 29, 37}
oidExtensionAuthorityKeyId = []int{2, 5, 29, 35}
oidExtensionBasicConstraints = []int{2, 5, 29, 19}
oidExtensionSubjectAltName = []int{2, 5, 29, 17}
@@ -791,7 +1023,7 @@ var (
)
func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
- ret = make([]pkix.Extension, 7 /* maximum number of elements. */)
+ ret = make([]pkix.Extension, 8 /* maximum number of elements. */)
n := 0
if template.KeyUsage != 0 {
@@ -814,6 +1046,27 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
n++
}
+ if len(template.ExtKeyUsage) > 0 || len(template.UnknownExtKeyUsage) > 0 {
+ ret[n].Id = oidExtensionExtendedKeyUsage
+
+ var oids []asn1.ObjectIdentifier
+ for _, u := range template.ExtKeyUsage {
+ if oid, ok := oidFromExtKeyUsage(u); ok {
+ oids = append(oids, oid)
+ } else {
+ panic("internal error")
+ }
+ }
+
+ oids = append(oids, template.UnknownExtKeyUsage...)
+
+ ret[n].Value, err = asn1.Marshal(oids)
+ if err != nil {
+ return
+ }
+ n++
+ }
+
if template.BasicConstraintsValid {
ret[n].Id = oidExtensionBasicConstraints
ret[n].Value, err = asn1.Marshal(basicConstraints{template.IsCA, template.MaxPathLen})
@@ -842,11 +1095,22 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
n++
}
- if len(template.DNSNames) > 0 {
+ if len(template.DNSNames) > 0 || len(template.EmailAddresses) > 0 || len(template.IPAddresses) > 0 {
ret[n].Id = oidExtensionSubjectAltName
- rawValues := make([]asn1.RawValue, len(template.DNSNames))
- for i, name := range template.DNSNames {
- rawValues[i] = asn1.RawValue{Tag: 2, Class: 2, Bytes: []byte(name)}
+ var rawValues []asn1.RawValue
+ for _, name := range template.DNSNames {
+ rawValues = append(rawValues, asn1.RawValue{Tag: 2, Class: 2, Bytes: []byte(name)})
+ }
+ for _, email := range template.EmailAddresses {
+ rawValues = append(rawValues, asn1.RawValue{Tag: 1, Class: 2, Bytes: []byte(email)})
+ }
+ for _, rawIP := range template.IPAddresses {
+ // If possible, we always want to encode IPv4 addresses in 4 bytes.
+ ip := rawIP.To4()
+ if ip == nil {
+ ip = rawIP
+ }
+ rawValues = append(rawValues, asn1.RawValue{Tag: 7, Class: 2, Bytes: ip})
}
ret[n].Value, err = asn1.Marshal(rawValues)
if err != nil {
@@ -890,11 +1154,6 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
return ret[0:n], nil
}
-var (
- oidSHA1WithRSA = []int{1, 2, 840, 113549, 1, 1, 5}
- oidRSA = []int{1, 2, 840, 113549, 1, 1, 1}
-)
-
func subjectBytes(cert *Certificate) ([]byte, error) {
if len(cert.RawSubject) > 0 {
return cert.RawSubject, nil
@@ -905,8 +1164,9 @@ func subjectBytes(cert *Certificate) ([]byte, error) {
// CreateCertificate creates a new certificate based on a template. The
// following members of template are used: SerialNumber, Subject, NotBefore,
-// NotAfter, KeyUsage, BasicConstraintsValid, IsCA, MaxPathLen, SubjectKeyId,
-// DNSNames, PermittedDNSDomainsCritical, PermittedDNSDomains.
+// NotAfter, KeyUsage, ExtKeyUsage, UnknownExtKeyUsage, BasicConstraintsValid,
+// IsCA, MaxPathLen, SubjectKeyId, DNSNames, PermittedDNSDomainsCritical,
+// PermittedDNSDomains.
//
// The certificate is signed by parent. If parent is equal to template then the
// certificate is self-signed. The parameter pub is the public key of the
@@ -914,23 +1174,61 @@ func subjectBytes(cert *Certificate) ([]byte, error) {
//
// The returned slice is the certificate in DER encoding.
//
-// The only supported key type is RSA (*rsa.PublicKey for pub, *rsa.PrivateKey
-// for priv).
+// The only supported key types are RSA and ECDSA (*rsa.PublicKey or
+// *ecdsa.PublicKey for pub, *rsa.PrivateKey or *ecdsa.PublicKey for priv).
func CreateCertificate(rand io.Reader, template, parent *Certificate, pub interface{}, priv interface{}) (cert []byte, err error) {
- rsaPub, ok := pub.(*rsa.PublicKey)
- if !ok {
- return nil, errors.New("x509: non-RSA public keys not supported")
+ var publicKeyBytes []byte
+ var publicKeyAlgorithm pkix.AlgorithmIdentifier
+
+ switch pub := pub.(type) {
+ case *rsa.PublicKey:
+ publicKeyBytes, err = asn1.Marshal(rsaPublicKey{
+ N: pub.N,
+ E: pub.E,
+ })
+ publicKeyAlgorithm.Algorithm = oidPublicKeyRSA
+ case *ecdsa.PublicKey:
+ oid, ok := oidFromNamedCurve(pub.Curve)
+ if !ok {
+ return nil, errors.New("x509: unknown elliptic curve")
+ }
+ publicKeyAlgorithm.Algorithm = oidPublicKeyECDSA
+ var paramBytes []byte
+ paramBytes, err = asn1.Marshal(oid)
+ if err != nil {
+ return
+ }
+ publicKeyAlgorithm.Parameters.FullBytes = paramBytes
+ publicKeyBytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y)
+ default:
+ return nil, errors.New("x509: only RSA and ECDSA public keys supported")
}
- rsaPriv, ok := priv.(*rsa.PrivateKey)
- if !ok {
- return nil, errors.New("x509: non-RSA private keys not supported")
+ var signatureAlgorithm pkix.AlgorithmIdentifier
+ var hashFunc crypto.Hash
+
+ switch priv := priv.(type) {
+ case *rsa.PrivateKey:
+ signatureAlgorithm.Algorithm = oidSignatureSHA1WithRSA
+ hashFunc = crypto.SHA1
+ case *ecdsa.PrivateKey:
+ switch priv.Curve {
+ case elliptic.P224(), elliptic.P256():
+ hashFunc = crypto.SHA256
+ signatureAlgorithm.Algorithm = oidSignatureECDSAWithSHA256
+ case elliptic.P384():
+ hashFunc = crypto.SHA384
+ signatureAlgorithm.Algorithm = oidSignatureECDSAWithSHA384
+ case elliptic.P521():
+ hashFunc = crypto.SHA512
+ signatureAlgorithm.Algorithm = oidSignatureECDSAWithSHA512
+ default:
+ return nil, errors.New("x509: unknown elliptic curve")
+ }
+ default:
+ return nil, errors.New("x509: only RSA and ECDSA private keys supported")
}
- asn1PublicKey, err := asn1.Marshal(rsaPublicKey{
- N: rsaPub.N,
- E: rsaPub.E,
- })
if err != nil {
return
}
@@ -954,15 +1252,15 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub interf
return
}
- encodedPublicKey := asn1.BitString{BitLength: len(asn1PublicKey) * 8, Bytes: asn1PublicKey}
+ encodedPublicKey := asn1.BitString{BitLength: len(publicKeyBytes) * 8, Bytes: publicKeyBytes}
c := tbsCertificate{
Version: 2,
SerialNumber: template.SerialNumber,
- SignatureAlgorithm: pkix.AlgorithmIdentifier{Algorithm: oidSHA1WithRSA},
+ SignatureAlgorithm: signatureAlgorithm,
Issuer: asn1.RawValue{FullBytes: asn1Issuer},
- Validity: validity{template.NotBefore, template.NotAfter},
+ Validity: validity{template.NotBefore.UTC(), template.NotAfter.UTC()},
Subject: asn1.RawValue{FullBytes: asn1Subject},
- PublicKey: publicKeyInfo{nil, pkix.AlgorithmIdentifier{Algorithm: oidRSA}, encodedPublicKey},
+ PublicKey: publicKeyInfo{nil, publicKeyAlgorithm, encodedPublicKey},
Extensions: extensions,
}
@@ -973,11 +1271,24 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub interf
c.Raw = tbsCertContents
- h := sha1.New()
+ h := hashFunc.New()
h.Write(tbsCertContents)
digest := h.Sum(nil)
- signature, err := rsa.SignPKCS1v15(rand, rsaPriv, crypto.SHA1, digest)
+ var signature []byte
+
+ switch priv := priv.(type) {
+ case *rsa.PrivateKey:
+ signature, err = rsa.SignPKCS1v15(rand, priv, hashFunc, digest)
+ case *ecdsa.PrivateKey:
+ var r, s *big.Int
+ if r, s, err = ecdsa.Sign(rand, priv, digest); err == nil {
+ signature, err = asn1.Marshal(ecdsaSignature{r, s})
+ }
+ default:
+ panic("internal error")
+ }
+
if err != nil {
return
}
@@ -985,7 +1296,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub interf
cert, err = asn1.Marshal(certificate{
nil,
c,
- pkix.AlgorithmIdentifier{Algorithm: oidSHA1WithRSA},
+ signatureAlgorithm,
asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
})
return
@@ -1037,8 +1348,8 @@ func (c *Certificate) CreateCRL(rand io.Reader, priv interface{}, revokedCerts [
Algorithm: oidSignatureSHA1WithRSA,
},
Issuer: c.Subject.ToRDNSequence(),
- ThisUpdate: now,
- NextUpdate: expiry,
+ ThisUpdate: now.UTC(),
+ NextUpdate: expiry.UTC(),
RevokedCertificates: revokedCerts,
}
diff --git a/src/pkg/crypto/x509/x509_test.go b/src/pkg/crypto/x509/x509_test.go
index f0327b012..abd4fe84d 100644
--- a/src/pkg/crypto/x509/x509_test.go
+++ b/src/pkg/crypto/x509/x509_test.go
@@ -7,14 +7,20 @@ package x509
import (
"bytes"
"crypto/dsa"
+ "crypto/ecdsa"
+ "crypto/elliptic"
"crypto/rand"
"crypto/rsa"
+ _ "crypto/sha256"
+ _ "crypto/sha512"
"crypto/x509/pkix"
"encoding/asn1"
"encoding/base64"
"encoding/hex"
"encoding/pem"
"math/big"
+ "net"
+ "reflect"
"testing"
"time"
)
@@ -169,6 +175,49 @@ func TestMatchHostnames(t *testing.T) {
}
}
+func TestMatchIP(t *testing.T) {
+ // Check that pattern matching is working.
+ c := &Certificate{
+ DNSNames: []string{"*.foo.bar.baz"},
+ Subject: pkix.Name{
+ CommonName: "*.foo.bar.baz",
+ },
+ }
+ err := c.VerifyHostname("quux.foo.bar.baz")
+ if err != nil {
+ t.Fatalf("VerifyHostname(quux.foo.bar.baz): %v", err)
+ }
+
+ // But check that if we change it to be matching against an IP address,
+ // it is rejected.
+ c = &Certificate{
+ DNSNames: []string{"*.2.3.4"},
+ Subject: pkix.Name{
+ CommonName: "*.2.3.4",
+ },
+ }
+ err = c.VerifyHostname("1.2.3.4")
+ if err == nil {
+ t.Fatalf("VerifyHostname(1.2.3.4) should have failed, did not")
+ }
+
+ c = &Certificate{
+ IPAddresses: []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("::1")},
+ }
+ err = c.VerifyHostname("127.0.0.1")
+ if err != nil {
+ t.Fatalf("VerifyHostname(127.0.0.1): %v", err)
+ }
+ err = c.VerifyHostname("::1")
+ if err != nil {
+ t.Fatalf("VerifyHostname(::1): %v", err)
+ }
+ err = c.VerifyHostname("[::1]")
+ if err != nil {
+ t.Fatalf("VerifyHostname([::1]): %v", err)
+ }
+}
+
func TestCertificateParse(t *testing.T) {
s, _ := hex.DecodeString(certBytes)
certs, err := ParseCertificates(s)
@@ -237,65 +286,220 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
random := rand.Reader
block, _ := pem.Decode([]byte(pemPrivateKey))
- priv, err := ParsePKCS1PrivateKey(block.Bytes)
+ rsaPriv, err := ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
- t.Errorf("Failed to parse private key: %s", err)
- return
+ t.Fatalf("Failed to parse private key: %s", err)
}
- commonName := "test.example.com"
- template := Certificate{
- SerialNumber: big.NewInt(1),
- Subject: pkix.Name{
- CommonName: commonName,
- Organization: []string{"Acme Co"},
- },
- NotBefore: time.Unix(1000, 0),
- NotAfter: time.Unix(100000, 0),
+ ecdsaPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ if err != nil {
+ t.Fatalf("Failed to generate ECDSA key: %s", err)
+ }
- SubjectKeyId: []byte{1, 2, 3, 4},
- KeyUsage: KeyUsageCertSign,
+ tests := []struct {
+ name string
+ pub, priv interface{}
+ checkSig bool
+ }{
+ {"RSA/RSA", &rsaPriv.PublicKey, rsaPriv, true},
+ {"RSA/ECDSA", &rsaPriv.PublicKey, ecdsaPriv, false},
+ {"ECDSA/RSA", &ecdsaPriv.PublicKey, rsaPriv, false},
+ {"ECDSA/ECDSA", &ecdsaPriv.PublicKey, ecdsaPriv, true},
+ }
- BasicConstraintsValid: true,
- IsCA: true,
- DNSNames: []string{"test.example.com"},
+ testExtKeyUsage := []ExtKeyUsage{ExtKeyUsageClientAuth, ExtKeyUsageServerAuth}
+ testUnknownExtKeyUsage := []asn1.ObjectIdentifier{[]int{1, 2, 3}, []int{3, 2, 1}}
- PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}},
- PermittedDNSDomains: []string{".example.com", "example.com"},
- }
+ for _, test := range tests {
+ commonName := "test.example.com"
+ template := Certificate{
+ SerialNumber: big.NewInt(1),
+ Subject: pkix.Name{
+ CommonName: commonName,
+ Organization: []string{"Σ Acme Co"},
+ },
+ NotBefore: time.Unix(1000, 0),
+ NotAfter: time.Unix(100000, 0),
- derBytes, err := CreateCertificate(random, &template, &template, &priv.PublicKey, priv)
- if err != nil {
- t.Errorf("Failed to create certificate: %s", err)
- return
- }
+ SubjectKeyId: []byte{1, 2, 3, 4},
+ KeyUsage: KeyUsageCertSign,
- cert, err := ParseCertificate(derBytes)
- if err != nil {
- t.Errorf("Failed to parse certificate: %s", err)
- return
- }
+ ExtKeyUsage: testExtKeyUsage,
+ UnknownExtKeyUsage: testUnknownExtKeyUsage,
- if len(cert.PolicyIdentifiers) != 1 || !cert.PolicyIdentifiers[0].Equal(template.PolicyIdentifiers[0]) {
- t.Errorf("Failed to parse policy identifiers: got:%#v want:%#v", cert.PolicyIdentifiers, template.PolicyIdentifiers)
- }
+ BasicConstraintsValid: true,
+ IsCA: true,
- if len(cert.PermittedDNSDomains) != 2 || cert.PermittedDNSDomains[0] != ".example.com" || cert.PermittedDNSDomains[1] != "example.com" {
- t.Errorf("Failed to parse name constraints: %#v", cert.PermittedDNSDomains)
- }
+ DNSNames: []string{"test.example.com"},
+ EmailAddresses: []string{"gopher@golang.org"},
+ IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1).To4(), net.ParseIP("2001:4860:0:2001::68")},
- if cert.Subject.CommonName != commonName {
- t.Errorf("Subject wasn't correctly copied from the template. Got %s, want %s", cert.Subject.CommonName, commonName)
- }
+ PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}},
+ PermittedDNSDomains: []string{".example.com", "example.com"},
+ }
+
+ derBytes, err := CreateCertificate(random, &template, &template, test.pub, test.priv)
+ if err != nil {
+ t.Errorf("%s: failed to create certificate: %s", test.name, err)
+ continue
+ }
+
+ cert, err := ParseCertificate(derBytes)
+ if err != nil {
+ t.Errorf("%s: failed to parse certificate: %s", test.name, err)
+ continue
+ }
+
+ if len(cert.PolicyIdentifiers) != 1 || !cert.PolicyIdentifiers[0].Equal(template.PolicyIdentifiers[0]) {
+ t.Errorf("%s: failed to parse policy identifiers: got:%#v want:%#v", test.name, cert.PolicyIdentifiers, template.PolicyIdentifiers)
+ }
+
+ if len(cert.PermittedDNSDomains) != 2 || cert.PermittedDNSDomains[0] != ".example.com" || cert.PermittedDNSDomains[1] != "example.com" {
+ t.Errorf("%s: failed to parse name constraints: %#v", test.name, cert.PermittedDNSDomains)
+ }
+
+ if cert.Subject.CommonName != commonName {
+ t.Errorf("%s: subject wasn't correctly copied from the template. Got %s, want %s", test.name, cert.Subject.CommonName, commonName)
+ }
+
+ if cert.Issuer.CommonName != commonName {
+ t.Errorf("%s: issuer wasn't correctly copied from the template. Got %s, want %s", test.name, cert.Issuer.CommonName, commonName)
+ }
+
+ if !reflect.DeepEqual(cert.ExtKeyUsage, testExtKeyUsage) {
+ t.Errorf("%s: extkeyusage wasn't correctly copied from the template. Got %v, want %v", test.name, cert.ExtKeyUsage, testExtKeyUsage)
+ }
- if cert.Issuer.CommonName != commonName {
- t.Errorf("Issuer wasn't correctly copied from the template. Got %s, want %s", cert.Issuer.CommonName, commonName)
+ if !reflect.DeepEqual(cert.UnknownExtKeyUsage, testUnknownExtKeyUsage) {
+ t.Errorf("%s: unknown extkeyusage wasn't correctly copied from the template. Got %v, want %v", test.name, cert.UnknownExtKeyUsage, testUnknownExtKeyUsage)
+ }
+
+ if !reflect.DeepEqual(cert.DNSNames, template.DNSNames) {
+ t.Errorf("%s: SAN DNS names differ from template. Got %v, want %v", test.name, cert.DNSNames, template.DNSNames)
+ }
+
+ if !reflect.DeepEqual(cert.EmailAddresses, template.EmailAddresses) {
+ t.Errorf("%s: SAN emails differ from template. Got %v, want %v", test.name, cert.EmailAddresses, template.EmailAddresses)
+ }
+
+ if !reflect.DeepEqual(cert.IPAddresses, template.IPAddresses) {
+ t.Errorf("%s: SAN IPs differ from template. Got %v, want %v", test.name, cert.IPAddresses, template.IPAddresses)
+ }
+
+ if test.checkSig {
+ err = cert.CheckSignatureFrom(cert)
+ if err != nil {
+ t.Errorf("%s: signature verification failed: %s", test.name, err)
+ }
+ }
}
+}
- err = cert.CheckSignatureFrom(cert)
- if err != nil {
- t.Errorf("Signature verification failed: %s", err)
- return
+// Self-signed certificate using ECDSA with SHA1 & secp256r1
+var ecdsaSHA1CertPem = `
+-----BEGIN CERTIFICATE-----
+MIICDjCCAbUCCQDF6SfN0nsnrjAJBgcqhkjOPQQBMIGPMQswCQYDVQQGEwJVUzET
+MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEVMBMG
+A1UECgwMR29vZ2xlLCBJbmMuMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEG
+CSqGSIb3DQEJARYUZ29sYW5nLWRldkBnbWFpbC5jb20wHhcNMTIwNTIwMjAyMDUw
+WhcNMjIwNTE4MjAyMDUwWjCBjzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlm
+b3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFTATBgNVBAoMDEdvb2dsZSwg
+SW5jLjEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20xIzAhBgkqhkiG9w0BCQEWFGdv
+bGFuZy1kZXZAZ21haWwuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/Wgn
+WQDo5+bz71T0327ERgd5SDDXFbXLpzIZDXTkjpe8QTEbsF+ezsQfrekrpDPC4Cd3
+P9LY0tG+aI8IyVKdUjAJBgcqhkjOPQQBA0gAMEUCIGlsqMcRqWVIWTD6wXwe6Jk2
+DKxL46r/FLgJYnzBEH99AiEA3fBouObsvV1R3oVkb4BQYnD4/4LeId6lAT43YvyV
+a/A=
+-----END CERTIFICATE-----
+`
+
+// Self-signed certificate using ECDSA with SHA256 & secp256r1
+var ecdsaSHA256p256CertPem = `
+-----BEGIN CERTIFICATE-----
+MIICDzCCAbYCCQDlsuMWvgQzhTAKBggqhkjOPQQDAjCBjzELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFTAT
+BgNVBAoMDEdvb2dsZSwgSW5jLjEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20xIzAh
+BgkqhkiG9w0BCQEWFGdvbGFuZy1kZXZAZ21haWwuY29tMB4XDTEyMDUyMTAwMTkx
+NloXDTIyMDUxOTAwMTkxNlowgY8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
+Zm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRUwEwYDVQQKDAxHb29nbGUs
+IEluYy4xFzAVBgNVBAMMDnd3dy5nb29nbGUuY29tMSMwIQYJKoZIhvcNAQkBFhRn
+b2xhbmctZGV2QGdtYWlsLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPMt
+2ErhxAty5EJRu9yM+MTy+hUXm3pdW1ensAv382KoGExSXAFWP7pjJnNtHO+XSwVm
+YNtqjcAGFKpweoN//kQwCgYIKoZIzj0EAwIDRwAwRAIgIYSaUA/IB81gjbIw/hUV
+70twxJr5EcgOo0hLp3Jm+EYCIFDO3NNcgmURbJ1kfoS3N/0O+irUtoPw38YoNkqJ
+h5wi
+-----END CERTIFICATE-----
+`
+
+// Self-signed certificate using ECDSA with SHA256 & secp384r1
+var ecdsaSHA256p384CertPem = `
+-----BEGIN CERTIFICATE-----
+MIICSjCCAdECCQDje/no7mXkVzAKBggqhkjOPQQDAjCBjjELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDAS
+BgNVBAoMC0dvb2dsZSwgSW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEG
+CSqGSIb3DQEJARYUZ29sYW5nLWRldkBnbWFpbC5jb20wHhcNMTIwNTIxMDYxMDM0
+WhcNMjIwNTE5MDYxMDM0WjCBjjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlm
+b3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDASBgNVBAoMC0dvb2dsZSwg
+SW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEGCSqGSIb3DQEJARYUZ29s
+YW5nLWRldkBnbWFpbC5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARRuzRNIKRK
+jIktEmXanNmrTR/q/FaHXLhWRZ6nHWe26Fw7Rsrbk+VjGy4vfWtNn7xSFKrOu5ze
+qxKnmE0h5E480MNgrUiRkaGO2GMJJVmxx20aqkXOk59U8yGA4CghE6MwCgYIKoZI
+zj0EAwIDZwAwZAIwBZEN8gvmRmfeP/9C1PRLzODIY4JqWub2PLRT4mv9GU+yw3Gr
+PU9A3CHMdEcdw/MEAjBBO1lId8KOCh9UZunsSMfqXiVurpzmhWd6VYZ/32G+M+Mh
+3yILeYQzllt/g0rKVRk=
+-----END CERTIFICATE-----
+`
+
+// Self-signed certificate using ECDSA with SHA384 & secp521r1
+var ecdsaSHA384p521CertPem = `
+-----BEGIN CERTIFICATE-----
+MIICljCCAfcCCQDhp1AFD/ahKjAKBggqhkjOPQQDAzCBjjELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDAS
+BgNVBAoMC0dvb2dsZSwgSW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEG
+CSqGSIb3DQEJARYUZ29sYW5nLWRldkBnbWFpbC5jb20wHhcNMTIwNTIxMTUwNDI5
+WhcNMjIwNTE5MTUwNDI5WjCBjjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlm
+b3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDASBgNVBAoMC0dvb2dsZSwg
+SW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEGCSqGSIb3DQEJARYUZ29s
+YW5nLWRldkBnbWFpbC5jb20wgZswEAYHKoZIzj0CAQYFK4EEACMDgYYABACqx9Rv
+IssRs1LWYcNN+WffwlHw4Tv3y8/LIAA9MF1ZScIonU9nRMxt4a2uGJVCPDw6JHpz
+PaYc0E9puLoE9AfKpwFr59Jkot7dBg55SKPEFkddoip/rvmN7NPAWjMBirOwjOkm
+8FPthvPhGPqsu9AvgVuHu3PosWiHGNrhh379pva8MzAKBggqhkjOPQQDAwOBjAAw
+gYgCQgEHNmswkUdPpHqrVxp9PvLVl+xxPuHBkT+75z9JizyxtqykHQo9Uh6SWCYH
+BF9KLolo01wMt8DjoYP5Fb3j5MH7xwJCAbWZzTOp4l4DPkIvAh4LeC4VWbwPPyqh
+kBg71w/iEcSY3wUKgHGcJJrObZw7wys91I5kENljqw/Samdr3ka+jBJa
+-----END CERTIFICATE-----
+`
+
+var ecdsaTests = []struct {
+ sigAlgo SignatureAlgorithm
+ pemCert string
+}{
+ {ECDSAWithSHA1, ecdsaSHA1CertPem},
+ {ECDSAWithSHA256, ecdsaSHA256p256CertPem},
+ {ECDSAWithSHA256, ecdsaSHA256p384CertPem},
+ {ECDSAWithSHA384, ecdsaSHA384p521CertPem},
+}
+
+func TestECDSA(t *testing.T) {
+ for i, test := range ecdsaTests {
+ pemBlock, _ := pem.Decode([]byte(test.pemCert))
+ cert, err := ParseCertificate(pemBlock.Bytes)
+ if err != nil {
+ t.Errorf("%d: failed to parse certificate: %s", i, err)
+ continue
+ }
+ if sa := cert.SignatureAlgorithm; sa != test.sigAlgo {
+ t.Errorf("%d: signature algorithm is %v, want %v", i, sa, test.sigAlgo)
+ }
+ if parsedKey, ok := cert.PublicKey.(*ecdsa.PublicKey); !ok {
+ t.Errorf("%d: wanted an ECDSA public key but found: %#v", i, parsedKey)
+ }
+ if pka := cert.PublicKeyAlgorithm; pka != ECDSA {
+ t.Errorf("%d: public key algorithm is %v, want ECDSA", i, pka)
+ }
+ if err = cert.CheckSignatureFrom(cert); err != nil {
+ t.Errorf("%d: certificate verification failed: %s", i, err)
+ }
}
}
@@ -374,7 +578,7 @@ func TestVerifyCertificateWithDSASignature(t *testing.T) {
}
// test cert is self-signed
if err = cert.CheckSignatureFrom(cert); err != nil {
- t.Fatalf("DSA Certificate verfication failed: %s", err)
+ t.Fatalf("DSA Certificate verification failed: %s", err)
}
}