aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/crypto
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2011-01-21 18:19:03 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-01-21 18:19:03 +0000
commitff5f50c52c421d75940ef9392211e3ab24d71332 (patch)
tree27d8768fb1d25696d3c40b42535eb5e073c278da /libgo/go/crypto
parentd6ed1c8903e728f4233122554bab5910853338bd (diff)
downloadgcc-ff5f50c52c421d75940ef9392211e3ab24d71332.zip
gcc-ff5f50c52c421d75940ef9392211e3ab24d71332.tar.gz
gcc-ff5f50c52c421d75940ef9392211e3ab24d71332.tar.bz2
Remove the types float and complex.
Update to current version of Go library. Update testsuite for removed types. * go-lang.c (go_langhook_init): Omit float_type_size when calling go_create_gogo. * go-c.h: Update declaration of go_create_gogo. From-SVN: r169098
Diffstat (limited to 'libgo/go/crypto')
-rw-r--r--libgo/go/crypto/block/cipher.go1
-rw-r--r--libgo/go/crypto/cipher/cbc.go78
-rw-r--r--libgo/go/crypto/cipher/cbc_aes_test.go (renamed from libgo/go/crypto/block/cbc_aes_test.go)35
-rw-r--r--libgo/go/crypto/cipher/cfb.go64
-rw-r--r--libgo/go/crypto/cipher/cfb_test.go35
-rw-r--r--libgo/go/crypto/cipher/cipher.go63
-rw-r--r--libgo/go/crypto/cipher/common_test.go28
-rw-r--r--libgo/go/crypto/cipher/ctr.go51
-rw-r--r--libgo/go/crypto/cipher/ctr_aes_test.go (renamed from libgo/go/crypto/block/ctr_aes_test.go)41
-rw-r--r--libgo/go/crypto/cipher/io.go57
-rw-r--r--libgo/go/crypto/cipher/ocfb.go112
-rw-r--r--libgo/go/crypto/cipher/ocfb_test.go39
-rw-r--r--libgo/go/crypto/cipher/ofb.go44
-rw-r--r--libgo/go/crypto/cipher/ofb_test.go101
-rw-r--r--libgo/go/crypto/elliptic/elliptic.go376
-rw-r--r--libgo/go/crypto/elliptic/elliptic_test.go331
-rw-r--r--libgo/go/crypto/hmac/hmac.go4
-rw-r--r--libgo/go/crypto/hmac/hmac_test.go109
-rw-r--r--libgo/go/crypto/openpgp/armor/armor.go220
-rw-r--r--libgo/go/crypto/openpgp/armor/armor_test.go97
-rw-r--r--libgo/go/crypto/openpgp/armor/encode.go162
-rw-r--r--libgo/go/crypto/openpgp/error/error.go46
-rw-r--r--libgo/go/crypto/openpgp/s2k/s2k.go146
-rw-r--r--libgo/go/crypto/openpgp/s2k/s2k_test.go94
-rw-r--r--libgo/go/crypto/rc4/rc4.go10
-rw-r--r--libgo/go/crypto/rc4/rc4_test.go2
-rw-r--r--libgo/go/crypto/rsa/pkcs1v15.go3
-rw-r--r--libgo/go/crypto/tls/ca_set.go1
-rw-r--r--libgo/go/crypto/tls/cipher_suites.go102
-rw-r--r--libgo/go/crypto/tls/common.go142
-rw-r--r--libgo/go/crypto/tls/conn.go161
-rw-r--r--libgo/go/crypto/tls/conn_test.go52
-rw-r--r--libgo/go/crypto/tls/generate_cert.go13
-rw-r--r--libgo/go/crypto/tls/handshake_client.go77
-rw-r--r--libgo/go/crypto/tls/handshake_client_test.go211
-rw-r--r--libgo/go/crypto/tls/handshake_messages.go113
-rw-r--r--libgo/go/crypto/tls/handshake_messages_test.go5
-rw-r--r--libgo/go/crypto/tls/handshake_server.go111
-rw-r--r--libgo/go/crypto/tls/handshake_server_test.go435
-rw-r--r--libgo/go/crypto/tls/key_agreement.go246
-rw-r--r--libgo/go/crypto/tls/prf.go33
-rw-r--r--libgo/go/crypto/tls/prf_test.go2
-rw-r--r--libgo/go/crypto/tls/tls.go48
-rw-r--r--libgo/go/crypto/twofish/twofish.go358
-rw-r--r--libgo/go/crypto/twofish/twofish_test.go129
-rw-r--r--libgo/go/crypto/x509/x509.go113
-rw-r--r--libgo/go/crypto/x509/x509_test.go8
47 files changed, 4319 insertions, 390 deletions
diff --git a/libgo/go/crypto/block/cipher.go b/libgo/go/crypto/block/cipher.go
index a50d05c..e1099e9 100644
--- a/libgo/go/crypto/block/cipher.go
+++ b/libgo/go/crypto/block/cipher.go
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// The block package is deprecated, use cipher instead.
// The block package implements standard block cipher modes
// that can be wrapped around low-level block cipher implementations.
// See http://csrc.nist.gov/groups/ST/toolkit/BCM/current_modes.html
diff --git a/libgo/go/crypto/cipher/cbc.go b/libgo/go/crypto/cipher/cbc.go
new file mode 100644
index 0000000..4632f88
--- /dev/null
+++ b/libgo/go/crypto/cipher/cbc.go
@@ -0,0 +1,78 @@
+// 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.
+
+// Cipher block chaining (CBC) mode.
+
+// CBC provides confidentiality by xoring (chaining) each plaintext block
+// with the previous ciphertext block before applying the block cipher.
+
+// See NIST SP 800-38A, pp 10-11
+
+package cipher
+
+type cbc struct {
+ b Block
+ blockSize int
+ iv []byte
+ tmp []byte
+}
+
+func newCBC(b Block, iv []byte) *cbc {
+ return &cbc{
+ b: b,
+ blockSize: b.BlockSize(),
+ iv: dup(iv),
+ tmp: make([]byte, b.BlockSize()),
+ }
+}
+
+type cbcEncrypter cbc
+
+// NewCBCEncrypter returns a BlockMode which encrypts in cipher block chaining
+// mode, using the given Block. The length of iv must be the same as the
+// Block's block size.
+func NewCBCEncrypter(b Block, iv []byte) BlockMode {
+ return (*cbcEncrypter)(newCBC(b, iv))
+}
+
+func (x *cbcEncrypter) BlockSize() int { return x.blockSize }
+
+func (x *cbcEncrypter) CryptBlocks(dst, src []byte) {
+ for len(src) > 0 {
+ for i := 0; i < x.blockSize; i++ {
+ x.iv[i] ^= src[i]
+ }
+ x.b.Encrypt(x.iv, x.iv)
+ for i := 0; i < x.blockSize; i++ {
+ dst[i] = x.iv[i]
+ }
+ src = src[x.blockSize:]
+ dst = dst[x.blockSize:]
+ }
+}
+
+type cbcDecrypter cbc
+
+// NewCBCDecrypter returns a BlockMode which decrypts in cipher block chaining
+// mode, using the given Block. The length of iv must be the same as the
+// Block's block size as must match the iv used to encrypt the data.
+func NewCBCDecrypter(b Block, iv []byte) BlockMode {
+ return (*cbcDecrypter)(newCBC(b, iv))
+}
+
+func (x *cbcDecrypter) BlockSize() int { return x.blockSize }
+
+func (x *cbcDecrypter) CryptBlocks(dst, src []byte) {
+ for len(src) > 0 {
+ x.b.Decrypt(x.tmp, src[:x.blockSize])
+ for i := 0; i < x.blockSize; i++ {
+ x.tmp[i] ^= x.iv[i]
+ x.iv[i] = src[i]
+ dst[i] = x.tmp[i]
+ }
+
+ src = src[x.blockSize:]
+ dst = dst[x.blockSize:]
+ }
+}
diff --git a/libgo/go/crypto/block/cbc_aes_test.go b/libgo/go/crypto/cipher/cbc_aes_test.go
index 5e8cb35..944ca1b 100644
--- a/libgo/go/crypto/block/cbc_aes_test.go
+++ b/libgo/go/crypto/cipher/cbc_aes_test.go
@@ -8,24 +8,21 @@
// Special Publication 800-38A, ``Recommendation for Block Cipher
// Modes of Operation,'' 2001 Edition, pp. 24-29.
-package block
+package cipher
import (
"bytes"
"crypto/aes"
- "io"
"testing"
)
-type cbcTest struct {
+var cbcAESTests = []struct {
name string
key []byte
iv []byte
in []byte
out []byte
-}
-
-var cbcAESTests = []cbcTest{
+}{
// NIST SP 800-38A pp 27-29
{
"CBC-AES128",
@@ -75,28 +72,18 @@ func TestCBC_AES(t *testing.T) {
continue
}
- var crypt bytes.Buffer
- w := NewCBCEncrypter(c, tt.iv, &crypt)
- var r io.Reader = bytes.NewBuffer(tt.in)
- n, err := io.Copy(w, r)
- if n != int64(len(tt.in)) || err != nil {
- t.Errorf("%s: CBCEncrypter io.Copy = %d, %v want %d, nil", test, n, err, len(tt.in))
- } else if d := crypt.Bytes(); !same(tt.out, d) {
+ encrypter := NewCBCEncrypter(c, tt.iv)
+ d := make([]byte, len(tt.in))
+ encrypter.CryptBlocks(d, tt.in)
+ if !bytes.Equal(tt.out, d) {
t.Errorf("%s: CBCEncrypter\nhave %x\nwant %x", test, d, tt.out)
}
- var plain bytes.Buffer
- r = NewCBCDecrypter(c, tt.iv, bytes.NewBuffer(tt.out))
- w = &plain
- n, err = io.Copy(w, r)
- if n != int64(len(tt.out)) || err != nil {
- t.Errorf("%s: CBCDecrypter io.Copy = %d, %v want %d, nil", test, n, err, len(tt.out))
- } else if d := plain.Bytes(); !same(tt.in, d) {
+ decrypter := NewCBCDecrypter(c, tt.iv)
+ p := make([]byte, len(d))
+ decrypter.CryptBlocks(p, d)
+ if !bytes.Equal(tt.in, p) {
t.Errorf("%s: CBCDecrypter\nhave %x\nwant %x", test, d, tt.in)
}
-
- if t.Failed() {
- break
- }
}
}
diff --git a/libgo/go/crypto/cipher/cfb.go b/libgo/go/crypto/cipher/cfb.go
new file mode 100644
index 0000000..d14165a
--- /dev/null
+++ b/libgo/go/crypto/cipher/cfb.go
@@ -0,0 +1,64 @@
+// 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.
+
+// CFB (Cipher Feedback) Mode.
+
+package cipher
+
+type cfb struct {
+ b Block
+ out []byte
+ outUsed int
+ decrypt bool
+}
+
+// NewCFBEncrypter returns a Stream which encrypts with cipher feedback mode,
+// using the given Block. The iv must be the same length as the Block's block
+// size.
+func NewCFBEncrypter(block Block, iv []byte) Stream {
+ return newCFB(block, iv, false)
+}
+
+// NewCFBDecrypter returns a Stream which decrypts with cipher feedback mode,
+// using the given Block. The iv must be the same length as the Block's block
+// size.
+func NewCFBDecrypter(block Block, iv []byte) Stream {
+ return newCFB(block, iv, true)
+}
+
+func newCFB(block Block, iv []byte, decrypt bool) Stream {
+ blockSize := block.BlockSize()
+ if len(iv) != blockSize {
+ return nil
+ }
+
+ x := &cfb{
+ b: block,
+ out: make([]byte, blockSize),
+ outUsed: 0,
+ decrypt: decrypt,
+ }
+ block.Encrypt(x.out, iv)
+
+ return x
+}
+
+func (x *cfb) XORKeyStream(dst, src []byte) {
+ for i := 0; i < len(src); i++ {
+ if x.outUsed == len(x.out) {
+ x.b.Encrypt(x.out, x.out)
+ x.outUsed = 0
+ }
+
+ if x.decrypt {
+ t := src[i]
+ dst[i] = src[i] ^ x.out[x.outUsed]
+ x.out[x.outUsed] = t
+ } else {
+ x.out[x.outUsed] ^= src[i]
+ dst[i] = x.out[x.outUsed]
+ }
+ x.outUsed++
+ }
+}
diff --git a/libgo/go/crypto/cipher/cfb_test.go b/libgo/go/crypto/cipher/cfb_test.go
new file mode 100644
index 0000000..9547bfc
--- /dev/null
+++ b/libgo/go/crypto/cipher/cfb_test.go
@@ -0,0 +1,35 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cipher
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/rand"
+ "testing"
+)
+
+func TestCFB(t *testing.T) {
+ block, err := aes.NewCipher(commonKey128)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ plaintext := []byte("this is the plaintext")
+ iv := make([]byte, block.BlockSize())
+ rand.Reader.Read(iv)
+ cfb := NewCFBEncrypter(block, iv)
+ ciphertext := make([]byte, len(plaintext))
+ cfb.XORKeyStream(ciphertext, plaintext)
+
+ cfbdec := NewCFBDecrypter(block, iv)
+ plaintextCopy := make([]byte, len(plaintext))
+ cfbdec.XORKeyStream(plaintextCopy, ciphertext)
+
+ if !bytes.Equal(plaintextCopy, plaintext) {
+ t.Errorf("got: %x, want: %x", plaintextCopy, plaintext)
+ }
+}
diff --git a/libgo/go/crypto/cipher/cipher.go b/libgo/go/crypto/cipher/cipher.go
new file mode 100644
index 0000000..50516b2
--- /dev/null
+++ b/libgo/go/crypto/cipher/cipher.go
@@ -0,0 +1,63 @@
+// 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.
+
+// The cipher package implements standard block cipher modes
+// that can be wrapped around low-level block cipher implementations.
+// See http://csrc.nist.gov/groups/ST/toolkit/BCM/current_modes.html
+// and NIST Special Publication 800-38A.
+package cipher
+
+// A Block represents an implementation of block cipher
+// using a given key. It provides the capability to encrypt
+// or decrypt individual blocks. The mode implementations
+// extend that capability to streams of blocks.
+type Block interface {
+ // BlockSize returns the cipher's block size.
+ BlockSize() int
+
+ // Encrypt encrypts the first block in src into dst.
+ // Dst and src may point at the same memory.
+ Encrypt(dst, src []byte)
+
+ // Decrypt decrypts the first block in src into dst.
+ // Dst and src may point at the same memory.
+ Decrypt(dst, src []byte)
+}
+
+// A Stream represents a stream cipher.
+type Stream interface {
+ // XORKeyStream XORs each byte in the given slice with a byte from the
+ // cipher's key stream. Dst and src may point to the same memory.
+ XORKeyStream(dst, src []byte)
+}
+
+// A BlockMode represents a block cipher running in a block-based mode (CBC,
+// ECB etc).
+type BlockMode interface {
+ // BlockSize returns the mode's block size.
+ BlockSize() int
+
+ // CryptBlocks encrypts or decrypts a number of blocks. The length of
+ // src must be a multiple of the block size. Dst and src may point to
+ // the same memory.
+ CryptBlocks(dst, src []byte)
+}
+
+// Utility routines
+
+func shift1(dst, src []byte) byte {
+ var b byte
+ for i := len(src) - 1; i >= 0; i-- {
+ bb := src[i] >> 7
+ dst[i] = src[i]<<1 | b
+ b = bb
+ }
+ return b
+}
+
+func dup(p []byte) []byte {
+ q := make([]byte, len(p))
+ copy(q, p)
+ return q
+}
diff --git a/libgo/go/crypto/cipher/common_test.go b/libgo/go/crypto/cipher/common_test.go
new file mode 100644
index 0000000..fb75575
--- /dev/null
+++ b/libgo/go/crypto/cipher/common_test.go
@@ -0,0 +1,28 @@
+// 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 cipher
+
+// Common values for tests.
+
+var commonInput = []byte{
+ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+ 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10,
+}
+
+var commonKey128 = []byte{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}
+
+var commonKey192 = []byte{
+ 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
+ 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b,
+}
+
+var commonKey256 = []byte{
+ 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
+ 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4,
+}
+
+var commonIV = []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}
diff --git a/libgo/go/crypto/cipher/ctr.go b/libgo/go/crypto/cipher/ctr.go
new file mode 100644
index 0000000..04436ec
--- /dev/null
+++ b/libgo/go/crypto/cipher/ctr.go
@@ -0,0 +1,51 @@
+// 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.
+
+// Counter (CTR) mode.
+
+// CTR converts a block cipher into a stream cipher by
+// repeatedly encrypting an incrementing counter and
+// xoring the resulting stream of data with the input.
+
+// See NIST SP 800-38A, pp 13-15
+
+package cipher
+
+type ctr struct {
+ b Block
+ ctr []byte
+ out []byte
+ outUsed int
+}
+
+// NewCTR returns a Stream which encrypts/decrypts using the given Block in
+// counter mode. The length of iv must be the same as the Block's block size.
+func NewCTR(block Block, iv []byte) Stream {
+ return &ctr{
+ b: block,
+ ctr: dup(iv),
+ out: make([]byte, len(iv)),
+ outUsed: len(iv),
+ }
+}
+
+func (x *ctr) XORKeyStream(dst, src []byte) {
+ for i := 0; i < len(src); i++ {
+ if x.outUsed == len(x.ctr) {
+ x.b.Encrypt(x.out, x.ctr)
+ x.outUsed = 0
+
+ // Increment counter
+ for i := len(x.ctr) - 1; i >= 0; i-- {
+ x.ctr[i]++
+ if x.ctr[i] != 0 {
+ break
+ }
+ }
+ }
+
+ dst[i] = src[i] ^ x.out[x.outUsed]
+ x.outUsed++
+ }
+}
diff --git a/libgo/go/crypto/block/ctr_aes_test.go b/libgo/go/crypto/cipher/ctr_aes_test.go
index ce5fdd5..8dca996 100644
--- a/libgo/go/crypto/block/ctr_aes_test.go
+++ b/libgo/go/crypto/cipher/ctr_aes_test.go
@@ -8,26 +8,23 @@
// Special Publication 800-38A, ``Recommendation for Block Cipher
// Modes of Operation,'' 2001 Edition, pp. 55-58.
-package block
+package cipher
import (
"bytes"
"crypto/aes"
- "io"
"testing"
)
-type ctrTest struct {
+var commonCounter = []byte{0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}
+
+var ctrAESTests = []struct {
name string
key []byte
iv []byte
in []byte
out []byte
-}
-
-var commonCounter = []byte{0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}
-
-var ctrAESTests = []ctrTest{
+}{
// NIST SP 800-38A pp 55-58
{
"CTR-AES128",
@@ -78,28 +75,22 @@ func TestCTR_AES(t *testing.T) {
}
for j := 0; j <= 5; j += 5 {
- var crypt bytes.Buffer
in := tt.in[0 : len(tt.in)-j]
- w := NewCTRWriter(c, tt.iv, &crypt)
- var r io.Reader = bytes.NewBuffer(in)
- n, err := io.Copy(w, r)
- if n != int64(len(in)) || err != nil {
- t.Errorf("%s/%d: CTRWriter io.Copy = %d, %v want %d, nil", test, len(in), n, err, len(in))
- } else if d, out := crypt.Bytes(), tt.out[0:len(in)]; !same(out, d) {
- t.Errorf("%s/%d: CTRWriter\ninpt %x\nhave %x\nwant %x", test, len(in), in, d, out)
+ ctr := NewCTR(c, tt.iv)
+ encrypted := make([]byte, len(in))
+ ctr.XORKeyStream(encrypted, in)
+ if out := tt.out[0:len(in)]; !bytes.Equal(out, encrypted) {
+ t.Errorf("%s/%d: CTR\ninpt %x\nhave %x\nwant %x", test, len(in), in, encrypted, out)
}
}
for j := 0; j <= 7; j += 7 {
- var plain bytes.Buffer
- out := tt.out[0 : len(tt.out)-j]
- r := NewCTRReader(c, tt.iv, bytes.NewBuffer(out))
- w := &plain
- n, err := io.Copy(w, r)
- if n != int64(len(out)) || err != nil {
- t.Errorf("%s/%d: CTRReader io.Copy = %d, %v want %d, nil", test, len(out), n, err, len(out))
- } else if d, in := plain.Bytes(), tt.in[0:len(out)]; !same(in, d) {
- t.Errorf("%s/%d: CTRReader\nhave %x\nwant %x", test, len(out), d, in)
+ in := tt.out[0 : len(tt.out)-j]
+ ctr := NewCTR(c, tt.iv)
+ plain := make([]byte, len(in))
+ ctr.XORKeyStream(plain, in)
+ if out := tt.in[0:len(in)]; !bytes.Equal(out, plain) {
+ t.Errorf("%s/%d: CTRReader\nhave %x\nwant %x", test, len(out), plain, out)
}
}
diff --git a/libgo/go/crypto/cipher/io.go b/libgo/go/crypto/cipher/io.go
new file mode 100644
index 0000000..97f40b8
--- /dev/null
+++ b/libgo/go/crypto/cipher/io.go
@@ -0,0 +1,57 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cipher
+
+import (
+ "os"
+ "io"
+)
+
+// The Stream* objects are so simple that all their members are public. Users
+// can create them themselves.
+
+// StreamReader wraps a Stream into an io.Reader. It simply calls XORKeyStream
+// to process each slice of data which passes through.
+type StreamReader struct {
+ S Stream
+ R io.Reader
+}
+
+func (r StreamReader) Read(dst []byte) (n int, err os.Error) {
+ n, err = r.R.Read(dst)
+ r.S.XORKeyStream(dst[:n], dst[:n])
+ return
+}
+
+// StreamWriter wraps a Stream into an io.Writer. It simply calls XORKeyStream
+// to process each slice of data which passes through. If any Write call
+// returns short then the StreamWriter is out of sync and must be discarded.
+type StreamWriter struct {
+ S Stream
+ W io.Writer
+ Err os.Error
+}
+
+func (w StreamWriter) Write(src []byte) (n int, err os.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)
+ if n != len(src) {
+ if err == nil { // should never happen
+ err = io.ErrShortWrite
+ }
+ w.Err = err
+ }
+ return
+}
+
+func (w StreamWriter) Close() os.Error {
+ // This saves us from either requiring a WriteCloser or having a
+ // StreamWriterCloser.
+ return w.W.(io.Closer).Close()
+}
diff --git a/libgo/go/crypto/cipher/ocfb.go b/libgo/go/crypto/cipher/ocfb.go
new file mode 100644
index 0000000..43cb5a5
--- /dev/null
+++ b/libgo/go/crypto/cipher/ocfb.go
@@ -0,0 +1,112 @@
+// 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.
+
+// OpenPGP CFB Mode. http://tools.ietf.org/html/rfc4880#section-13.9
+
+package cipher
+
+type ocfbEncrypter struct {
+ b Block
+ fre []byte
+ outUsed int
+}
+
+// NewOCFBEncrypter returns a Stream which encrypts data with OpenPGP's cipher
+// feedback mode using the given Block, and an initial amount of ciphertext.
+// randData must be random bytes and be the same length as the Block's block
+// size.
+func NewOCFBEncrypter(block Block, randData []byte) (Stream, []byte) {
+ blockSize := block.BlockSize()
+ if len(randData) != blockSize {
+ return nil, nil
+ }
+
+ x := &ocfbEncrypter{
+ b: block,
+ fre: make([]byte, blockSize),
+ outUsed: 0,
+ }
+ prefix := make([]byte, blockSize+2)
+
+ block.Encrypt(x.fre, x.fre)
+ for i := 0; i < blockSize; i++ {
+ prefix[i] = randData[i] ^ x.fre[i]
+ }
+
+ block.Encrypt(x.fre, prefix[:blockSize])
+ prefix[blockSize] = x.fre[0] ^ randData[blockSize-2]
+ prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1]
+
+ block.Encrypt(x.fre, prefix[2:])
+ return x, prefix
+}
+
+func (x *ocfbEncrypter) XORKeyStream(dst, src []byte) {
+ for i := 0; i < len(src); i++ {
+ if x.outUsed == len(x.fre) {
+ x.b.Encrypt(x.fre, x.fre)
+ x.outUsed = 0
+ }
+
+ x.fre[x.outUsed] ^= src[i]
+ dst[i] = x.fre[x.outUsed]
+ x.outUsed++
+ }
+}
+
+type ocfbDecrypter struct {
+ b Block
+ fre []byte
+ outUsed int
+}
+
+// NewOCFBDecrypter returns a Stream which decrypts data with OpenPGP's cipher
+// feedback mode using the given Block. Prefix must be the first blockSize + 2
+// bytes of the ciphertext, where blockSize is the Block's block size. If an
+// incorrect key is detected then nil is returned.
+func NewOCFBDecrypter(block Block, prefix []byte) Stream {
+ blockSize := block.BlockSize()
+ if len(prefix) != blockSize+2 {
+ return nil
+ }
+
+ x := &ocfbDecrypter{
+ b: block,
+ fre: make([]byte, blockSize),
+ outUsed: 0,
+ }
+ prefixCopy := make([]byte, len(prefix))
+ copy(prefixCopy, prefix)
+
+ block.Encrypt(x.fre, x.fre)
+ for i := 0; i < blockSize; i++ {
+ prefixCopy[i] ^= x.fre[i]
+ }
+
+ block.Encrypt(x.fre, prefix[:blockSize])
+ prefixCopy[blockSize] ^= x.fre[0]
+ prefixCopy[blockSize+1] ^= x.fre[1]
+
+ if prefixCopy[blockSize-2] != prefixCopy[blockSize] ||
+ prefixCopy[blockSize-1] != prefixCopy[blockSize+1] {
+ return nil
+ }
+
+ block.Encrypt(x.fre, prefix[2:])
+ return x
+}
+
+func (x *ocfbDecrypter) XORKeyStream(dst, src []byte) {
+ for i := 0; i < len(src); i++ {
+ if x.outUsed == len(x.fre) {
+ x.b.Encrypt(x.fre, x.fre)
+ x.outUsed = 0
+ }
+
+ c := src[i]
+ dst[i] = x.fre[x.outUsed] ^ src[i]
+ x.fre[x.outUsed] = c
+ x.outUsed++
+ }
+}
diff --git a/libgo/go/crypto/cipher/ocfb_test.go b/libgo/go/crypto/cipher/ocfb_test.go
new file mode 100644
index 0000000..289bb7c
--- /dev/null
+++ b/libgo/go/crypto/cipher/ocfb_test.go
@@ -0,0 +1,39 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cipher
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/rand"
+ "testing"
+)
+
+func TestOCFB(t *testing.T) {
+ block, err := aes.NewCipher(commonKey128)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ plaintext := []byte("this is the plaintext")
+ randData := make([]byte, block.BlockSize())
+ rand.Reader.Read(randData)
+ ocfb, prefix := NewOCFBEncrypter(block, randData)
+ ciphertext := make([]byte, len(plaintext))
+ ocfb.XORKeyStream(ciphertext, plaintext)
+
+ ocfbdec := NewOCFBDecrypter(block, prefix)
+ if ocfbdec == nil {
+ t.Error("NewOCFBDecrypter failed")
+ return
+ }
+ plaintextCopy := make([]byte, len(plaintext))
+ ocfbdec.XORKeyStream(plaintextCopy, ciphertext)
+
+ if !bytes.Equal(plaintextCopy, plaintext) {
+ t.Errorf("got: %x, want: %x", plaintextCopy, plaintext)
+ }
+}
diff --git a/libgo/go/crypto/cipher/ofb.go b/libgo/go/crypto/cipher/ofb.go
new file mode 100644
index 0000000..85e5f02
--- /dev/null
+++ b/libgo/go/crypto/cipher/ofb.go
@@ -0,0 +1,44 @@
+// 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.
+
+// OFB (Output Feedback) Mode.
+
+package cipher
+
+type ofb struct {
+ b Block
+ out []byte
+ outUsed int
+}
+
+// NewOFB returns a Stream that encrypts or decrypts using the block cipher b
+// in output feedback mode. The initialization vector iv's length must be equal
+// to b's block size.
+func NewOFB(b Block, iv []byte) Stream {
+ blockSize := b.BlockSize()
+ if len(iv) != blockSize {
+ return nil
+ }
+
+ x := &ofb{
+ b: b,
+ out: make([]byte, blockSize),
+ outUsed: 0,
+ }
+ b.Encrypt(x.out, iv)
+
+ return x
+}
+
+func (x *ofb) XORKeyStream(dst, src []byte) {
+ for i, s := range src {
+ if x.outUsed == len(x.out) {
+ x.b.Encrypt(x.out, x.out)
+ x.outUsed = 0
+ }
+
+ dst[i] = s ^ x.out[x.outUsed]
+ x.outUsed++
+ }
+}
diff --git a/libgo/go/crypto/cipher/ofb_test.go b/libgo/go/crypto/cipher/ofb_test.go
new file mode 100644
index 0000000..9b4495c
--- /dev/null
+++ b/libgo/go/crypto/cipher/ofb_test.go
@@ -0,0 +1,101 @@
+// 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.
+
+// OFB AES test vectors.
+
+// See U.S. National Institute of Standards and Technology (NIST)
+// Special Publication 800-38A, ``Recommendation for Block Cipher
+// Modes of Operation,'' 2001 Edition, pp. 52-55.
+
+package cipher
+
+import (
+ "bytes"
+ "crypto/aes"
+ "testing"
+)
+
+type ofbTest struct {
+ name string
+ key []byte
+ iv []byte
+ in []byte
+ out []byte
+}
+
+var ofbTests = []ofbTest{
+ // NIST SP 800-38A pp 52-55
+ {
+ "OFB-AES128",
+ commonKey128,
+ commonIV,
+ commonInput,
+ []byte{
+ 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a,
+ 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03, 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25,
+ 0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6, 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc,
+ 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78, 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e,
+ },
+ },
+ {
+ "OFB-AES192",
+ commonKey192,
+ commonIV,
+ commonInput,
+ []byte{
+ 0xcd, 0xc8, 0x0d, 0x6f, 0xdd, 0xf1, 0x8c, 0xab, 0x34, 0xc2, 0x59, 0x09, 0xc9, 0x9a, 0x41, 0x74,
+ 0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c, 0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01,
+ 0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f, 0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2,
+ 0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e, 0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a,
+ },
+ },
+ {
+ "OFB-AES256",
+ commonKey256,
+ commonIV,
+ commonInput,
+ []byte{
+ 0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b, 0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60,
+ 0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a, 0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d,
+ 0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed, 0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08,
+ 0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8, 0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84,
+ },
+ },
+}
+
+func TestOFB(t *testing.T) {
+ for _, tt := range ofbTests {
+ test := tt.name
+
+ c, err := aes.NewCipher(tt.key)
+ if err != nil {
+ t.Errorf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err)
+ continue
+ }
+
+ for j := 0; j <= 5; j += 5 {
+ plaintext := tt.in[0 : len(tt.in)-j]
+ ofb := NewOFB(c, tt.iv)
+ ciphertext := make([]byte, len(plaintext))
+ ofb.XORKeyStream(ciphertext, plaintext)
+ if !bytes.Equal(ciphertext, tt.out[:len(plaintext)]) {
+ t.Errorf("%s/%d: encrypting\ninput % x\nhave % x\nwant % x", test, len(plaintext), plaintext, ciphertext, tt.out)
+ }
+ }
+
+ for j := 0; j <= 5; j += 5 {
+ ciphertext := tt.out[0 : len(tt.in)-j]
+ ofb := NewOFB(c, tt.iv)
+ plaintext := make([]byte, len(ciphertext))
+ ofb.XORKeyStream(plaintext, ciphertext)
+ if !bytes.Equal(plaintext, tt.in[:len(ciphertext)]) {
+ t.Errorf("%s/%d: decrypting\nhave % x\nwant % x", test, len(ciphertext), plaintext, tt.in)
+ }
+ }
+
+ if t.Failed() {
+ break
+ }
+ }
+}
diff --git a/libgo/go/crypto/elliptic/elliptic.go b/libgo/go/crypto/elliptic/elliptic.go
new file mode 100644
index 0000000..beac45c
--- /dev/null
+++ b/libgo/go/crypto/elliptic/elliptic.go
@@ -0,0 +1,376 @@
+// 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.
+
+// The elliptic package implements several standard elliptic curves over prime
+// fields
+package elliptic
+
+// This package operates, internally, on Jacobian coordinates. For a given
+// (x, y) position on the curve, the Jacobian coordinates are (x1, y1, z1)
+// where x = x1/z1² and y = y1/z1³. The greatest speedups come when the whole
+// calculation can be performed within the transform (as in ScalarMult and
+// ScalarBaseMult). But even for Add and Double, it's faster to apply and
+// reverse the transform than to operate in affine coordinates.
+
+import (
+ "big"
+ "io"
+ "os"
+ "sync"
+)
+
+// A Curve represents a short-form Weierstrass curve with a=-3.
+// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw.html
+type Curve struct {
+ P *big.Int // the order of the underlying field
+ B *big.Int // the constant of the curve equation
+ Gx, Gy *big.Int // (x,y) of the base point
+ BitSize int // the size of the underlying field
+}
+
+// IsOnCurve returns true if the given (x,y) lies on the curve.
+func (curve *Curve) IsOnCurve(x, y *big.Int) bool {
+ // y² = x³ - 3x + b
+ y2 := new(big.Int).Mul(y, y)
+ y2.Mod(y2, curve.P)
+
+ x3 := new(big.Int).Mul(x, x)
+ x3.Mul(x3, x)
+
+ threeX := new(big.Int).Lsh(x, 1)
+ threeX.Add(threeX, x)
+
+ x3.Sub(x3, threeX)
+ x3.Add(x3, curve.B)
+ x3.Mod(x3, curve.P)
+
+ return x3.Cmp(y2) == 0
+}
+
+// affineFromJacobian reverses the Jacobian transform. See the comment at the
+// top of the file.
+func (curve *Curve) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) {
+ zinv := new(big.Int).ModInverse(z, curve.P)
+ zinvsq := new(big.Int).Mul(zinv, zinv)
+
+ xOut = new(big.Int).Mul(x, zinvsq)
+ xOut.Mod(xOut, curve.P)
+ zinvsq.Mul(zinvsq, zinv)
+ yOut = new(big.Int).Mul(y, zinvsq)
+ yOut.Mod(yOut, curve.P)
+ return
+}
+
+// Add returns the sum of (x1,y1) and (x2,y2)
+func (curve *Curve) 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))
+}
+
+// addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and
+// (x2, y2, z2) and returns their sum, also in Jacobian form.
+func (curve *Curve) 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
+ z1z1 := new(big.Int).Mul(z1, z1)
+ z1z1.Mod(z1z1, curve.P)
+ z2z2 := new(big.Int).Mul(z2, z2)
+ z2z2.Mod(z2z2, curve.P)
+
+ u1 := new(big.Int).Mul(x1, z2z2)
+ u1.Mod(u1, curve.P)
+ u2 := new(big.Int).Mul(x2, z1z1)
+ u2.Mod(u2, curve.P)
+ h := new(big.Int).Sub(u2, u1)
+ if h.Sign() == -1 {
+ h.Add(h, curve.P)
+ }
+ i := new(big.Int).Lsh(h, 1)
+ i.Mul(i, i)
+ j := new(big.Int).Mul(h, i)
+
+ s1 := new(big.Int).Mul(y1, z2)
+ s1.Mul(s1, z2z2)
+ s1.Mod(s1, curve.P)
+ s2 := new(big.Int).Mul(y2, z1)
+ s2.Mul(s2, z1z1)
+ s2.Mod(s2, curve.P)
+ r := new(big.Int).Sub(s2, s1)
+ if r.Sign() == -1 {
+ r.Add(r, curve.P)
+ }
+ r.Lsh(r, 1)
+ v := new(big.Int).Mul(u1, i)
+
+ x3 := new(big.Int).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)
+ v.Sub(v, x3)
+ y3.Mul(y3, v)
+ s1.Mul(s1, j)
+ s1.Lsh(s1, 1)
+ y3.Sub(y3, s1)
+ y3.Mod(y3, curve.P)
+
+ z3 := new(big.Int).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)
+
+ return x3, y3, z3
+}
+
+// Double returns 2*(x,y)
+func (curve *Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
+ z1 := new(big.Int).SetInt64(1)
+ return curve.affineFromJacobian(curve.doubleJacobian(x1, y1, z1))
+}
+
+// doubleJacobian takes a point in Jacobian coordinates, (x, y, z), and
+// returns its double, also in Jacobian form.
+func (curve *Curve) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.Int) {
+ // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
+ delta := new(big.Int).Mul(z, z)
+ delta.Mod(delta, curve.P)
+ gamma := new(big.Int).Mul(y, y)
+ gamma.Mod(gamma, curve.P)
+ alpha := new(big.Int).Sub(x, delta)
+ if alpha.Sign() == -1 {
+ alpha.Add(alpha, curve.P)
+ }
+ alpha2 := new(big.Int).Add(x, delta)
+ alpha.Mul(alpha, alpha2)
+ alpha2.Set(alpha)
+ alpha.Lsh(alpha, 1)
+ alpha.Add(alpha, alpha2)
+
+ beta := alpha2.Mul(x, gamma)
+
+ x3 := new(big.Int).Mul(alpha, alpha)
+ beta8 := new(big.Int).Lsh(beta, 3)
+ x3.Sub(x3, beta8)
+ for x3.Sign() == -1 {
+ x3.Add(x3, curve.P)
+ }
+ x3.Mod(x3, curve.P)
+
+ z3 := new(big.Int).Add(y, z)
+ z3.Mul(z3, z3)
+ z3.Sub(z3, gamma)
+ if z3.Sign() == -1 {
+ z3.Add(z3, curve.P)
+ }
+ z3.Sub(z3, delta)
+ if z3.Sign() == -1 {
+ z3.Add(z3, curve.P)
+ }
+ z3.Mod(z3, curve.P)
+
+ beta.Lsh(beta, 2)
+ beta.Sub(beta, x3)
+ if beta.Sign() == -1 {
+ beta.Add(beta, curve.P)
+ }
+ y3 := alpha.Mul(alpha, beta)
+
+ gamma.Mul(gamma, gamma)
+ gamma.Lsh(gamma, 3)
+ gamma.Mod(gamma, curve.P)
+
+ y3.Sub(y3, gamma)
+ if y3.Sign() == -1 {
+ y3.Add(y3, curve.P)
+ }
+ y3.Mod(y3, curve.P)
+
+ return x3, y3, z3
+}
+
+// ScalarMult returns k*(Bx,By) where k is a number in big-endian form.
+func (curve *Curve) 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
+
+ seenFirstTrue := false
+ for _, byte := range k {
+ for bitNum := 0; bitNum < 8; bitNum++ {
+ if seenFirstTrue {
+ 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)
+ }
+ }
+ byte <<= 1
+ }
+ }
+
+ if !seenFirstTrue {
+ return nil, nil
+ }
+
+ return curve.affineFromJacobian(x, y, z)
+}
+
+// ScalarBaseMult returns k*G, where G is the base point of the group and k is
+// an integer in big-endian form.
+func (curve *Curve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
+ return curve.ScalarMult(curve.Gx, curve.Gy, k)
+}
+
+var mask = []byte{0xff, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f}
+
+// GenerateKey returns a public/private key pair. The private key is generated
+// using the given reader, which must return random data.
+func (curve *Curve) GenerateKey(rand io.Reader) (priv []byte, x, y *big.Int, err os.Error) {
+ byteLen := (curve.BitSize + 7) >> 3
+ priv = make([]byte, byteLen)
+
+ for x == nil {
+ _, err = io.ReadFull(rand, priv)
+ if err != nil {
+ return
+ }
+ // We have to mask off any excess bits in the case that the size of the
+ // underlying field is not a whole number of bytes.
+ priv[0] &= mask[curve.BitSize%8]
+ // This is because, in tests, rand will return all zeros and we don't
+ // want to get the point at infinity and loop forever.
+ priv[1] ^= 0x42
+ x, y = curve.ScalarBaseMult(priv)
+ }
+ return
+}
+
+// Marshal converts a point into the form specified in section 4.3.6 of ANSI
+// X9.62.
+func (curve *Curve) Marshal(x, y *big.Int) []byte {
+ byteLen := (curve.BitSize + 7) >> 3
+
+ ret := make([]byte, 1+2*byteLen)
+ ret[0] = 4 // uncompressed point
+
+ xBytes := x.Bytes()
+ copy(ret[1+byteLen-len(xBytes):], xBytes)
+ yBytes := y.Bytes()
+ copy(ret[1+2*byteLen-len(yBytes):], yBytes)
+ return ret
+}
+
+// Unmarshal converts a point, serialised by Marshal, into an x, y pair. On
+// error, x = nil.
+func (curve *Curve) Unmarshal(data []byte) (x, y *big.Int) {
+ byteLen := (curve.BitSize + 7) >> 3
+ if len(data) != 1+2*byteLen {
+ return
+ }
+ if data[0] != 4 { // uncompressed form
+ return
+ }
+ x = new(big.Int).SetBytes(data[1 : 1+byteLen])
+ y = new(big.Int).SetBytes(data[1+byteLen:])
+ return
+}
+
+var initonce sync.Once
+var p224 *Curve
+var p256 *Curve
+var p384 *Curve
+var p521 *Curve
+
+func initAll() {
+ initP224()
+ initP256()
+ initP384()
+ initP521()
+}
+
+func initP224() {
+ // See FIPS 186-3, section D.2.2
+ p224 = new(Curve)
+ p224.P, _ = new(big.Int).SetString("26959946667150639794667015087019630673557916260026308143510066298881", 10)
+ p224.B, _ = new(big.Int).SetString("b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", 16)
+ p224.Gx, _ = new(big.Int).SetString("b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 16)
+ p224.Gy, _ = new(big.Int).SetString("bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34", 16)
+ p224.BitSize = 224
+}
+
+func initP256() {
+ // See FIPS 186-3, section D.2.3
+ p256 = new(Curve)
+ p256.P, _ = new(big.Int).SetString("115792089210356248762697446949407573530086143415290314195533631308867097853951", 10)
+ p256.B, _ = new(big.Int).SetString("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16)
+ p256.Gx, _ = new(big.Int).SetString("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16)
+ p256.Gy, _ = new(big.Int).SetString("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16)
+ p256.BitSize = 256
+}
+
+func initP384() {
+ // See FIPS 186-3, section D.2.4
+ p384 = new(Curve)
+ p384.P, _ = new(big.Int).SetString("39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319", 10)
+ p384.B, _ = new(big.Int).SetString("b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef", 16)
+ p384.Gx, _ = new(big.Int).SetString("aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7", 16)
+ p384.Gy, _ = new(big.Int).SetString("3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f", 16)
+ p384.BitSize = 384
+}
+
+func initP521() {
+ // See FIPS 186-3, section D.2.5
+ p521 = new(Curve)
+ p521.P, _ = new(big.Int).SetString("6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151", 10)
+ p521.B, _ = new(big.Int).SetString("051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", 16)
+ p521.Gx, _ = new(big.Int).SetString("c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", 16)
+ p521.Gy, _ = new(big.Int).SetString("11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", 16)
+ p521.BitSize = 521
+}
+
+// P224 returns a Curve which implements P-224 (see FIPS 186-3, section D.2.2)
+func P224() *Curve {
+ initonce.Do(initAll)
+ return p224
+}
+
+// P256 returns a Curve which implements P-256 (see FIPS 186-3, section D.2.3)
+func P256() *Curve {
+ initonce.Do(initAll)
+ return p256
+}
+
+// P384 returns a Curve which implements P-384 (see FIPS 186-3, section D.2.4)
+func P384() *Curve {
+ initonce.Do(initAll)
+ return p384
+}
+
+// P256 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/libgo/go/crypto/elliptic/elliptic_test.go b/libgo/go/crypto/elliptic/elliptic_test.go
new file mode 100644
index 0000000..6ae6fb9
--- /dev/null
+++ b/libgo/go/crypto/elliptic/elliptic_test.go
@@ -0,0 +1,331 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package elliptic
+
+import (
+ "big"
+ "crypto/rand"
+ "fmt"
+ "testing"
+)
+
+func TestOnCurve(t *testing.T) {
+ p224 := P224()
+ if !p224.IsOnCurve(p224.Gx, p224.Gy) {
+ t.Errorf("FAIL")
+ }
+}
+
+type baseMultTest struct {
+ k string
+ x, y string
+}
+
+var p224BaseMultTests = []baseMultTest{
+ {
+ "1",
+ "b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
+ "bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34",
+ },
+ {
+ "2",
+ "706a46dc76dcb76798e60e6d89474788d16dc18032d268fd1a704fa6",
+ "1c2b76a7bc25e7702a704fa986892849fca629487acf3709d2e4e8bb",
+ },
+ {
+ "3",
+ "df1b1d66a551d0d31eff822558b9d2cc75c2180279fe0d08fd896d04",
+ "a3f7f03cadd0be444c0aa56830130ddf77d317344e1af3591981a925",
+ },
+ {
+ "4",
+ "ae99feebb5d26945b54892092a8aee02912930fa41cd114e40447301",
+ "482580a0ec5bc47e88bc8c378632cd196cb3fa058a7114eb03054c9",
+ },
+ {
+ "5",
+ "31c49ae75bce7807cdff22055d94ee9021fedbb5ab51c57526f011aa",
+ "27e8bff1745635ec5ba0c9f1c2ede15414c6507d29ffe37e790a079b",
+ },
+ {
+ "6",
+ "1f2483f82572251fca975fea40db821df8ad82a3c002ee6c57112408",
+ "89faf0ccb750d99b553c574fad7ecfb0438586eb3952af5b4b153c7e",
+ },
+ {
+ "7",
+ "db2f6be630e246a5cf7d99b85194b123d487e2d466b94b24a03c3e28",
+ "f3a30085497f2f611ee2517b163ef8c53b715d18bb4e4808d02b963",
+ },
+ {
+ "8",
+ "858e6f9cc6c12c31f5df124aa77767b05c8bc021bd683d2b55571550",
+ "46dcd3ea5c43898c5c5fc4fdac7db39c2f02ebee4e3541d1e78047a",
+ },
+ {
+ "9",
+ "2fdcccfee720a77ef6cb3bfbb447f9383117e3daa4a07e36ed15f78d",
+ "371732e4f41bf4f7883035e6a79fcedc0e196eb07b48171697517463",
+ },
+ {
+ "10",
+ "aea9e17a306517eb89152aa7096d2c381ec813c51aa880e7bee2c0fd",
+ "39bb30eab337e0a521b6cba1abe4b2b3a3e524c14a3fe3eb116b655f",
+ },
+ {
+ "11",
+ "ef53b6294aca431f0f3c22dc82eb9050324f1d88d377e716448e507c",
+ "20b510004092e96636cfb7e32efded8265c266dfb754fa6d6491a6da",
+ },
+ {
+ "12",
+ "6e31ee1dc137f81b056752e4deab1443a481033e9b4c93a3044f4f7a",
+ "207dddf0385bfdeab6e9acda8da06b3bbef224a93ab1e9e036109d13",
+ },
+ {
+ "13",
+ "34e8e17a430e43289793c383fac9774247b40e9ebd3366981fcfaeca",
+ "252819f71c7fb7fbcb159be337d37d3336d7feb963724fdfb0ecb767",
+ },
+ {
+ "14",
+ "a53640c83dc208603ded83e4ecf758f24c357d7cf48088b2ce01e9fa",
+ "d5814cd724199c4a5b974a43685fbf5b8bac69459c9469bc8f23ccaf",
+ },
+ {
+ "15",
+ "baa4d8635511a7d288aebeedd12ce529ff102c91f97f867e21916bf9",
+ "979a5f4759f80f4fb4ec2e34f5566d595680a11735e7b61046127989",
+ },
+ {
+ "16",
+ "b6ec4fe1777382404ef679997ba8d1cc5cd8e85349259f590c4c66d",
+ "3399d464345906b11b00e363ef429221f2ec720d2f665d7dead5b482",
+ },
+ {
+ "17",
+ "b8357c3a6ceef288310e17b8bfeff9200846ca8c1942497c484403bc",
+ "ff149efa6606a6bd20ef7d1b06bd92f6904639dce5174db6cc554a26",
+ },
+ {
+ "18",
+ "c9ff61b040874c0568479216824a15eab1a838a797d189746226e4cc",
+ "ea98d60e5ffc9b8fcf999fab1df7e7ef7084f20ddb61bb045a6ce002",
+ },
+ {
+ "19",
+ "a1e81c04f30ce201c7c9ace785ed44cc33b455a022f2acdbc6cae83c",
+ "dcf1f6c3db09c70acc25391d492fe25b4a180babd6cea356c04719cd",
+ },
+ {
+ "20",
+ "fcc7f2b45df1cd5a3c0c0731ca47a8af75cfb0347e8354eefe782455",
+ "d5d7110274cba7cdee90e1a8b0d394c376a5573db6be0bf2747f530",
+ },
+ {
+ "112233445566778899",
+ "61f077c6f62ed802dad7c2f38f5c67f2cc453601e61bd076bb46179e",
+ "2272f9e9f5933e70388ee652513443b5e289dd135dcc0d0299b225e4",
+ },
+ {
+ "112233445566778899112233445566778899",
+ "29895f0af496bfc62b6ef8d8a65c88c613949b03668aab4f0429e35",
+ "3ea6e53f9a841f2019ec24bde1a75677aa9b5902e61081c01064de93",
+ },
+ {
+ "6950511619965839450988900688150712778015737983940691968051900319680",
+ "ab689930bcae4a4aa5f5cb085e823e8ae30fd365eb1da4aba9cf0379",
+ "3345a121bbd233548af0d210654eb40bab788a03666419be6fbd34e7",
+ },
+ {
+ "13479972933410060327035789020509431695094902435494295338570602119423",
+ "bdb6a8817c1f89da1c2f3dd8e97feb4494f2ed302a4ce2bc7f5f4025",
+ "4c7020d57c00411889462d77a5438bb4e97d177700bf7243a07f1680",
+ },
+ {
+ "13479971751745682581351455311314208093898607229429740618390390702079",
+ "d58b61aa41c32dd5eba462647dba75c5d67c83606c0af2bd928446a9",
+ "d24ba6a837be0460dd107ae77725696d211446c5609b4595976b16bd",
+ },
+ {
+ "13479972931865328106486971546324465392952975980343228160962702868479",
+ "dc9fa77978a005510980e929a1485f63716df695d7a0c18bb518df03",
+ "ede2b016f2ddffc2a8c015b134928275ce09e5661b7ab14ce0d1d403",
+ },
+ {
+ "11795773708834916026404142434151065506931607341523388140225443265536",
+ "499d8b2829cfb879c901f7d85d357045edab55028824d0f05ba279ba",
+ "bf929537b06e4015919639d94f57838fa33fc3d952598dcdbb44d638",
+ },
+ {
+ "784254593043826236572847595991346435467177662189391577090",
+ "8246c999137186632c5f9eddf3b1b0e1764c5e8bd0e0d8a554b9cb77",
+ "e80ed8660bc1cb17ac7d845be40a7a022d3306f116ae9f81fea65947",
+ },
+ {
+ "13479767645505654746623887797783387853576174193480695826442858012671",
+ "6670c20afcceaea672c97f75e2e9dd5c8460e54bb38538ebb4bd30eb",
+ "f280d8008d07a4caf54271f993527d46ff3ff46fd1190a3f1faa4f74",
+ },
+ {
+ "205688069665150753842126177372015544874550518966168735589597183",
+ "eca934247425cfd949b795cb5ce1eff401550386e28d1a4c5a8eb",
+ "d4c01040dba19628931bc8855370317c722cbd9ca6156985f1c2e9ce",
+ },
+ {
+ "13479966930919337728895168462090683249159702977113823384618282123295",
+ "ef353bf5c73cd551b96d596fbc9a67f16d61dd9fe56af19de1fba9cd",
+ "21771b9cdce3e8430c09b3838be70b48c21e15bc09ee1f2d7945b91f",
+ },
+ {
+ "50210731791415612487756441341851895584393717453129007497216",
+ "4036052a3091eb481046ad3289c95d3ac905ca0023de2c03ecd451cf",
+ "d768165a38a2b96f812586a9d59d4136035d9c853a5bf2e1c86a4993",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368041",
+ "fcc7f2b45df1cd5a3c0c0731ca47a8af75cfb0347e8354eefe782455",
+ "f2a28eefd8b345832116f1e574f2c6b2c895aa8c24941f40d8b80ad1",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368042",
+ "a1e81c04f30ce201c7c9ace785ed44cc33b455a022f2acdbc6cae83c",
+ "230e093c24f638f533dac6e2b6d01da3b5e7f45429315ca93fb8e634",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368043",
+ "c9ff61b040874c0568479216824a15eab1a838a797d189746226e4cc",
+ "156729f1a003647030666054e208180f8f7b0df2249e44fba5931fff",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368044",
+ "b8357c3a6ceef288310e17b8bfeff9200846ca8c1942497c484403bc",
+ "eb610599f95942df1082e4f9426d086fb9c6231ae8b24933aab5db",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368045",
+ "b6ec4fe1777382404ef679997ba8d1cc5cd8e85349259f590c4c66d",
+ "cc662b9bcba6f94ee4ff1c9c10bd6ddd0d138df2d099a282152a4b7f",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368046",
+ "baa4d8635511a7d288aebeedd12ce529ff102c91f97f867e21916bf9",
+ "6865a0b8a607f0b04b13d1cb0aa992a5a97f5ee8ca1849efb9ed8678",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368047",
+ "a53640c83dc208603ded83e4ecf758f24c357d7cf48088b2ce01e9fa",
+ "2a7eb328dbe663b5a468b5bc97a040a3745396ba636b964370dc3352",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368048",
+ "34e8e17a430e43289793c383fac9774247b40e9ebd3366981fcfaeca",
+ "dad7e608e380480434ea641cc82c82cbc92801469c8db0204f13489a",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368049",
+ "6e31ee1dc137f81b056752e4deab1443a481033e9b4c93a3044f4f7a",
+ "df82220fc7a4021549165325725f94c3410ddb56c54e161fc9ef62ee",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368050",
+ "ef53b6294aca431f0f3c22dc82eb9050324f1d88d377e716448e507c",
+ "df4aefffbf6d1699c930481cd102127c9a3d992048ab05929b6e5927",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368051",
+ "aea9e17a306517eb89152aa7096d2c381ec813c51aa880e7bee2c0fd",
+ "c644cf154cc81f5ade49345e541b4d4b5c1adb3eb5c01c14ee949aa2",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368052",
+ "2fdcccfee720a77ef6cb3bfbb447f9383117e3daa4a07e36ed15f78d",
+ "c8e8cd1b0be40b0877cfca1958603122f1e6914f84b7e8e968ae8b9e",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368053",
+ "858e6f9cc6c12c31f5df124aa77767b05c8bc021bd683d2b55571550",
+ "fb9232c15a3bc7673a3a03b0253824c53d0fd1411b1cabe2e187fb87",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368054",
+ "db2f6be630e246a5cf7d99b85194b123d487e2d466b94b24a03c3e28",
+ "f0c5cff7ab680d09ee11dae84e9c1072ac48ea2e744b1b7f72fd469e",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368055",
+ "1f2483f82572251fca975fea40db821df8ad82a3c002ee6c57112408",
+ "76050f3348af2664aac3a8b05281304ebc7a7914c6ad50a4b4eac383",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368056",
+ "31c49ae75bce7807cdff22055d94ee9021fedbb5ab51c57526f011aa",
+ "d817400e8ba9ca13a45f360e3d121eaaeb39af82d6001c8186f5f866",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368057",
+ "ae99feebb5d26945b54892092a8aee02912930fa41cd114e40447301",
+ "fb7da7f5f13a43b81774373c879cd32d6934c05fa758eeb14fcfab38",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368058",
+ "df1b1d66a551d0d31eff822558b9d2cc75c2180279fe0d08fd896d04",
+ "5c080fc3522f41bbb3f55a97cfecf21f882ce8cbb1e50ca6e67e56dc",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368059",
+ "706a46dc76dcb76798e60e6d89474788d16dc18032d268fd1a704fa6",
+ "e3d4895843da188fd58fb0567976d7b50359d6b78530c8f62d1b1746",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368060",
+ "b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
+ "42c89c774a08dc04b3dd201932bc8a5ea5f8b89bbb2a7e667aff81cd",
+ },
+}
+
+func TestBaseMult(t *testing.T) {
+ p224 := P224()
+ for i, e := range p224BaseMultTests {
+ k, ok := new(big.Int).SetString(e.k, 10)
+ if !ok {
+ t.Errorf("%d: bad value for k: %s", i, e.k)
+ }
+ x, y := p224.ScalarBaseMult(k.Bytes())
+ if fmt.Sprintf("%x", x) != e.x || fmt.Sprintf("%x", y) != e.y {
+ t.Errorf("%d: bad output for k=%s: got (%x, %s), want (%s, %s)", i, e.k, x, y, e.x, e.y)
+ }
+ }
+}
+
+func BenchmarkBaseMult(b *testing.B) {
+ b.ResetTimer()
+ p224 := P224()
+ e := p224BaseMultTests[25]
+ k, _ := new(big.Int).SetString(e.k, 10)
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ p224.ScalarBaseMult(k.Bytes())
+ }
+}
+
+func TestMarshal(t *testing.T) {
+ p224 := P224()
+ _, x, y, err := p224.GenerateKey(rand.Reader)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ serialised := p224.Marshal(x, y)
+ xx, yy := p224.Unmarshal(serialised)
+ if xx == nil {
+ t.Error("failed to unmarshal")
+ return
+ }
+ if xx.Cmp(x) != 0 || yy.Cmp(y) != 0 {
+ t.Error("unmarshal returned different values")
+ return
+ }
+}
diff --git a/libgo/go/crypto/hmac/hmac.go b/libgo/go/crypto/hmac/hmac.go
index 3b5aa13..298fb2c 100644
--- a/libgo/go/crypto/hmac/hmac.go
+++ b/libgo/go/crypto/hmac/hmac.go
@@ -11,6 +11,7 @@ package hmac
import (
"crypto/md5"
"crypto/sha1"
+ "crypto/sha256"
"hash"
"os"
)
@@ -94,3 +95,6 @@ func NewMD5(key []byte) hash.Hash { return New(md5.New, key) }
// NewSHA1 returns a new HMAC-SHA1 hash using the given key.
func NewSHA1(key []byte) hash.Hash { return New(sha1.New, key) }
+
+// NewSHA256 returns a new HMAC-SHA256 hash using the given key.
+func NewSHA256(key []byte) hash.Hash { return New(sha256.New, key) }
diff --git a/libgo/go/crypto/hmac/hmac_test.go b/libgo/go/crypto/hmac/hmac_test.go
index 1a50fa3..40adbad 100644
--- a/libgo/go/crypto/hmac/hmac_test.go
+++ b/libgo/go/crypto/hmac/hmac_test.go
@@ -17,9 +17,9 @@ type hmacTest struct {
out string
}
-// Tests from US FIPS 198
-// http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf
var hmacTests = []hmacTest{
+ // Tests from US FIPS 198
+ // http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf
{
NewSHA1,
[]byte{
@@ -73,6 +73,111 @@ var hmacTests = []hmacTest{
[]byte("what do ya want for nothing?"),
"750c783e6ab0b503eaa86e310a5db738",
},
+
+ // Tests from RFC 4231
+ {
+ NewSHA256,
+ []byte{
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b,
+ },
+ []byte("Hi There"),
+ "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7",
+ },
+ {
+ NewSHA256,
+ []byte("Jefe"),
+ []byte("what do ya want for nothing?"),
+ "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843",
+ },
+ {
+ NewSHA256,
+ []byte{
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa,
+ },
+ []byte{
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd,
+ },
+ "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe",
+ },
+ {
+ NewSHA256,
+ []byte{
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x19,
+ },
+ []byte{
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd,
+ },
+ "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b",
+ },
+ {
+ NewSHA256,
+ []byte{
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa,
+ },
+ []byte("Test Using Larger Than Block-Size Key - Hash Key First"),
+ "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54",
+ },
+ {
+ NewSHA256,
+ []byte{
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa,
+ },
+ []byte("This is a test using a larger than block-size key " +
+ "and a larger than block-size data. The key needs to " +
+ "be hashed before being used by the HMAC algorithm."),
+ "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2",
+ },
}
func TestHMAC(t *testing.T) {
diff --git a/libgo/go/crypto/openpgp/armor/armor.go b/libgo/go/crypto/openpgp/armor/armor.go
new file mode 100644
index 0000000..97080f6
--- /dev/null
+++ b/libgo/go/crypto/openpgp/armor/armor.go
@@ -0,0 +1,220 @@
+// 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 package implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is
+// very similar to PEM except that it has an additional CRC checksum.
+package armor
+
+import (
+ "bytes"
+ "crypto/openpgp/error"
+ "encoding/base64"
+ "encoding/line"
+ "io"
+ "os"
+)
+
+// A Block represents an OpenPGP armored structure.
+//
+// The encoded form is:
+// -----BEGIN Type-----
+// Headers
+//
+// base64-encoded Bytes
+// '=' base64 encoded checksum
+// -----END Type-----
+// where Headers is a possibly empty sequence of Key: Value lines.
+//
+// Since the armored data can be very large, this package presents a streaming
+// interface.
+type Block struct {
+ Type string // The type, taken from the preamble (i.e. "PGP SIGNATURE").
+ Header map[string]string // Optional headers.
+ Body io.Reader // A Reader from which the contents can be read
+ lReader lineReader
+ oReader openpgpReader
+}
+
+var ArmorCorrupt os.Error = error.StructuralError("armor invalid")
+
+const crc24Init = 0xb704ce
+const crc24Poly = 0x1864cfb
+const crc24Mask = 0xffffff
+
+// crc24 calculates the OpenPGP checksum as specified in RFC 4880, section 6.1
+func crc24(crc uint32, d []byte) uint32 {
+ for _, b := range d {
+ crc ^= uint32(b) << 16
+ for i := 0; i < 8; i++ {
+ crc <<= 1
+ if crc&0x1000000 != 0 {
+ crc ^= crc24Poly
+ }
+ }
+ }
+ return crc
+}
+
+var armorStart = []byte("-----BEGIN ")
+var armorEnd = []byte("-----END ")
+var armorEndOfLine = []byte("-----")
+
+// lineReader wraps a line based reader. It watches for the end of an armor
+// block and records the expected CRC value.
+type lineReader struct {
+ in *line.Reader
+ buf []byte
+ eof bool
+ crc uint32
+}
+
+func (l *lineReader) Read(p []byte) (n int, err os.Error) {
+ if l.eof {
+ return 0, os.EOF
+ }
+
+ if len(l.buf) > 0 {
+ n = copy(p, l.buf)
+ l.buf = l.buf[n:]
+ return
+ }
+
+ line, isPrefix, err := l.in.ReadLine()
+ if err != nil {
+ return
+ }
+ if isPrefix {
+ return 0, ArmorCorrupt
+ }
+
+ if len(line) == 5 && line[0] == '=' {
+ // This is the checksum line
+ var expectedBytes [3]byte
+ var m int
+ m, err = base64.StdEncoding.Decode(expectedBytes[0:], line[1:])
+ if m != 3 || err != nil {
+ return
+ }
+ l.crc = uint32(expectedBytes[0])<<16 |
+ uint32(expectedBytes[1])<<8 |
+ uint32(expectedBytes[2])
+
+ line, _, err = l.in.ReadLine()
+ if err != nil && err != os.EOF {
+ return
+ }
+ if !bytes.HasPrefix(line, armorEnd) {
+ return 0, ArmorCorrupt
+ }
+
+ l.eof = true
+ return 0, os.EOF
+ }
+
+ if len(line) != 64 {
+ return 0, ArmorCorrupt
+ }
+
+ n = copy(p, line)
+ bytesToSave := len(line) - n
+ if bytesToSave > 0 {
+ if cap(l.buf) < bytesToSave {
+ l.buf = make([]byte, 0, bytesToSave)
+ }
+ l.buf = l.buf[0:bytesToSave]
+ copy(l.buf, line[n:])
+ }
+
+ return
+}
+
+// openpgpReader passes Read calls to the underlying base64 decoder, but keeps
+// a running CRC of the resulting data and checks the CRC against the value
+// found by the lineReader at EOF.
+type openpgpReader struct {
+ lReader *lineReader
+ b64Reader io.Reader
+ currentCRC uint32
+}
+
+func (r *openpgpReader) Read(p []byte) (n int, err os.Error) {
+ n, err = r.b64Reader.Read(p)
+ r.currentCRC = crc24(r.currentCRC, p[:n])
+
+ if err == os.EOF {
+ if r.lReader.crc != uint32(r.currentCRC&crc24Mask) {
+ return 0, ArmorCorrupt
+ }
+ }
+
+ return
+}
+
+// Decode reads a PGP armored block from the given Reader. It will ignore
+// leading garbage. If it doesn't find a block, it will return nil, os.EOF. The
+// given Reader is not usable after calling this function: an arbitary amount
+// of data may have been read past the end of the block.
+func Decode(in io.Reader) (p *Block, err os.Error) {
+ r := line.NewReader(in, 100)
+ var line []byte
+ ignoreNext := false
+
+TryNextBlock:
+ p = nil
+
+ // Skip leading garbage
+ for {
+ ignoreThis := ignoreNext
+ line, ignoreNext, err = r.ReadLine()
+ if err != nil {
+ return
+ }
+ if ignoreNext || ignoreThis {
+ continue
+ }
+ line = bytes.TrimSpace(line)
+ if len(line) > len(armorStart)+len(armorEndOfLine) && bytes.HasPrefix(line, armorStart) {
+ break
+ }
+ }
+
+ p = new(Block)
+ p.Type = string(line[len(armorStart) : len(line)-len(armorEndOfLine)])
+ p.Header = make(map[string]string)
+ nextIsContinuation := false
+ var lastKey string
+
+ // Read headers
+ for {
+ isContinuation := nextIsContinuation
+ line, nextIsContinuation, err = r.ReadLine()
+ if err != nil {
+ p = nil
+ return
+ }
+ if isContinuation {
+ p.Header[lastKey] += string(line)
+ continue
+ }
+ line = bytes.TrimSpace(line)
+ if len(line) == 0 {
+ break
+ }
+
+ i := bytes.Index(line, []byte(": "))
+ if i == -1 {
+ goto TryNextBlock
+ }
+ lastKey = string(line[:i])
+ p.Header[lastKey] = string(line[i+2:])
+ }
+
+ p.lReader.in = r
+ p.oReader.currentCRC = crc24Init
+ p.oReader.lReader = &p.lReader
+ p.oReader.b64Reader = base64.NewDecoder(base64.StdEncoding, &p.lReader)
+ p.Body = &p.oReader
+
+ return
+}
diff --git a/libgo/go/crypto/openpgp/armor/armor_test.go b/libgo/go/crypto/openpgp/armor/armor_test.go
new file mode 100644
index 0000000..e4ffd41
--- /dev/null
+++ b/libgo/go/crypto/openpgp/armor/armor_test.go
@@ -0,0 +1,97 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package armor
+
+import (
+ "bytes"
+ "hash/adler32"
+ "io/ioutil"
+ "testing"
+)
+
+func TestDecodeEncode(t *testing.T) {
+ buf := bytes.NewBuffer([]byte(armorExample1))
+ result, err := Decode(buf)
+ if err != nil {
+ t.Error(err)
+ }
+ expectedType := "PGP SIGNATURE"
+ if result.Type != expectedType {
+ t.Errorf("result.Type: got:%s want:%s", result.Type, expectedType)
+ }
+ if len(result.Header) != 1 {
+ t.Errorf("len(result.Header): got:%d want:1", len(result.Header))
+ }
+ v, ok := result.Header["Version"]
+ if !ok || v != "GnuPG v1.4.10 (GNU/Linux)" {
+ t.Errorf("result.Header: got:%#v", result.Header)
+ }
+
+ contents, err := ioutil.ReadAll(result.Body)
+ if err != nil {
+ t.Error(err)
+ }
+
+ if adler32.Checksum(contents) != 0x789d7f00 {
+ t.Errorf("contents: got: %x", contents)
+ }
+
+ buf = bytes.NewBuffer(nil)
+ w, err := Encode(buf, result.Type, result.Header)
+ if err != nil {
+ t.Error(err)
+ }
+ _, err = w.Write(contents)
+ if err != nil {
+ t.Error(err)
+ }
+ w.Close()
+
+ if !bytes.Equal(buf.Bytes(), []byte(armorExample1)) {
+ t.Errorf("got: %s\nwant: %s", string(buf.Bytes()), armorExample1)
+ }
+}
+
+func TestLongHeader(t *testing.T) {
+ buf := bytes.NewBuffer([]byte(armorLongLine))
+ result, err := Decode(buf)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ value, ok := result.Header["Version"]
+ if !ok {
+ t.Errorf("missing Version header")
+ }
+ if value != longValueExpected {
+ t.Errorf("got: %s want: %s", value, longValueExpected)
+ }
+}
+
+const armorExample1 = `-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.10 (GNU/Linux)
+
+iQEcBAABAgAGBQJMtFESAAoJEKsQXJGvOPsVj40H/1WW6jaMXv4BW+1ueDSMDwM8
+kx1fLOXbVM5/Kn5LStZNt1jWWnpxdz7eq3uiqeCQjmqUoRde3YbB2EMnnwRbAhpp
+cacnAvy9ZQ78OTxUdNW1mhX5bS6q1MTEJnl+DcyigD70HG/yNNQD7sOPMdYQw0TA
+byQBwmLwmTsuZsrYqB68QyLHI+DUugn+kX6Hd2WDB62DKa2suoIUIHQQCd/ofwB3
+WfCYInXQKKOSxu2YOg2Eb4kLNhSMc1i9uKUWAH+sdgJh7NBgdoE4MaNtBFkHXRvv
+okWuf3+xA9ksp1npSY/mDvgHijmjvtpRDe6iUeqfCn8N9u9CBg8geANgaG8+QA4=
+=wfQG
+-----END PGP SIGNATURE-----`
+
+const armorLongLine = `-----BEGIN PGP SIGNATURE-----
+Version: 0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz
+
+iQEcBAABAgAGBQJMtFESAAoJEKsQXJGvOPsVj40H/1WW6jaMXv4BW+1ueDSMDwM8
+kx1fLOXbVM5/Kn5LStZNt1jWWnpxdz7eq3uiqeCQjmqUoRde3YbB2EMnnwRbAhpp
+cacnAvy9ZQ78OTxUdNW1mhX5bS6q1MTEJnl+DcyigD70HG/yNNQD7sOPMdYQw0TA
+byQBwmLwmTsuZsrYqB68QyLHI+DUugn+kX6Hd2WDB62DKa2suoIUIHQQCd/ofwB3
+WfCYInXQKKOSxu2YOg2Eb4kLNhSMc1i9uKUWAH+sdgJh7NBgdoE4MaNtBFkHXRvv
+okWuf3+xA9ksp1npSY/mDvgHijmjvtpRDe6iUeqfCn8N9u9CBg8geANgaG8+QA4=
+=wfQG
+-----END PGP SIGNATURE-----`
+
+const longValueExpected = "0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz"
diff --git a/libgo/go/crypto/openpgp/armor/encode.go b/libgo/go/crypto/openpgp/armor/encode.go
new file mode 100644
index 0000000..410e734
--- /dev/null
+++ b/libgo/go/crypto/openpgp/armor/encode.go
@@ -0,0 +1,162 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package armor
+
+import (
+ "encoding/base64"
+ "io"
+ "os"
+)
+
+var armorHeaderSep = []byte(": ")
+var blockEnd = []byte("\n=")
+var newline = []byte("\n")
+var armorEndOfLineOut = []byte("-----\n")
+
+// writeSlices writes its arguments to the given Writer.
+func writeSlices(out io.Writer, slices ...[]byte) (err os.Error) {
+ for _, s := range slices {
+ _, err := out.Write(s)
+ if err != nil {
+ return
+ }
+ }
+ return
+}
+
+// lineBreaker breaks data across several lines, all of the same byte length
+// (except possibly the last). Lines are broken with a single '\n'.
+type lineBreaker struct {
+ lineLength int
+ line []byte
+ used int
+ out io.Writer
+ haveWritten bool
+}
+
+func newLineBreaker(out io.Writer, lineLength int) *lineBreaker {
+ return &lineBreaker{
+ lineLength: lineLength,
+ line: make([]byte, lineLength),
+ used: 0,
+ out: out,
+ }
+}
+
+func (l *lineBreaker) Write(b []byte) (n int, err os.Error) {
+ n = len(b)
+
+ if n == 0 {
+ return
+ }
+
+ if l.used == 0 && l.haveWritten {
+ _, err = l.out.Write([]byte{'\n'})
+ if err != nil {
+ return
+ }
+ }
+
+ if l.used+len(b) < l.lineLength {
+ l.used += copy(l.line[l.used:], b)
+ return
+ }
+
+ l.haveWritten = true
+ _, err = l.out.Write(l.line[0:l.used])
+ if err != nil {
+ return
+ }
+ excess := l.lineLength - l.used
+ l.used = 0
+
+ _, err = l.out.Write(b[0:excess])
+ if err != nil {
+ return
+ }
+
+ _, err = l.Write(b[excess:])
+ return
+}
+
+func (l *lineBreaker) Close() (err os.Error) {
+ if l.used > 0 {
+ _, err = l.out.Write(l.line[0:l.used])
+ if err != nil {
+ return
+ }
+ }
+
+ return
+}
+
+// encoding keeps track of a running CRC24 over the data which has been written
+// to it and outputs a OpenPGP checksum when closed, followed by an armor
+// trailer.
+//
+// It's built into a stack of io.Writers:
+// encoding -> base64 encoder -> lineBreaker -> out
+type encoding struct {
+ out io.Writer
+ breaker *lineBreaker
+ b64 io.WriteCloser
+ crc uint32
+ blockType []byte
+}
+
+func (e *encoding) Write(data []byte) (n int, err os.Error) {
+ e.crc = crc24(e.crc, data)
+ return e.b64.Write(data)
+}
+
+func (e *encoding) Close() (err os.Error) {
+ err = e.b64.Close()
+ if err != nil {
+ return
+ }
+
+ var checksumBytes [3]byte
+ checksumBytes[0] = byte(e.crc >> 16)
+ checksumBytes[1] = byte(e.crc >> 8)
+ checksumBytes[2] = byte(e.crc)
+
+ var b64ChecksumBytes [4]byte
+ base64.StdEncoding.Encode(b64ChecksumBytes[:], checksumBytes[:])
+
+ return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine)
+}
+
+// Encode returns a WriteCloser which will encode the data written to it in
+// OpenPGP armor.
+func Encode(out io.Writer, blockType string, headers map[string]string) (w io.WriteCloser, err os.Error) {
+ bType := []byte(blockType)
+ err = writeSlices(out, armorStart, bType, armorEndOfLineOut)
+ if err != nil {
+ return
+ }
+
+ for k, v := range headers {
+ err = writeSlices(out, []byte(k), armorHeaderSep, []byte(v), newline)
+ if err != nil {
+ return
+ }
+ }
+
+ if len(headers) > 0 {
+ _, err := out.Write(newline)
+ if err != nil {
+ return
+ }
+ }
+
+ e := &encoding{
+ out: out,
+ breaker: newLineBreaker(out, 64),
+ crc: crc24Init,
+ blockType: bType,
+ }
+ e.b64 = base64.NewEncoder(base64.StdEncoding, e.breaker)
+ return e, nil
+}
diff --git a/libgo/go/crypto/openpgp/error/error.go b/libgo/go/crypto/openpgp/error/error.go
new file mode 100644
index 0000000..2d80ce3
--- /dev/null
+++ b/libgo/go/crypto/openpgp/error/error.go
@@ -0,0 +1,46 @@
+// 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 package contains common error types for the OpenPGP packages.
+package error
+
+// A StructuralError is returned when OpenPGP data is found to be syntactically
+// invalid.
+type StructuralError string
+
+func (s StructuralError) String() string {
+ return "OpenPGP data invalid: " + string(s)
+}
+
+// UnsupportedError indicates that, although the OpenPGP data is valid, it
+// makes use of currently unimplemented features.
+type UnsupportedError string
+
+func (s UnsupportedError) String() string {
+ return "OpenPGP feature unsupported: " + string(s)
+}
+
+// InvalidArgumentError indicates that the caller is in error and passed an
+// incorrect value.
+type InvalidArgumentError string
+
+func (i InvalidArgumentError) String() string {
+ return "OpenPGP argument invalid: " + string(i)
+}
+
+// SignatureError indicates that a syntactically valid signature failed to
+// validate.
+type SignatureError string
+
+func (b SignatureError) String() string {
+ return "OpenPGP signature invalid: " + string(b)
+}
+
+type keyIncorrect int
+
+func (ki keyIncorrect) String() string {
+ return "the given key was incorrect"
+}
+
+var KeyIncorrectError = keyIncorrect(0)
diff --git a/libgo/go/crypto/openpgp/s2k/s2k.go b/libgo/go/crypto/openpgp/s2k/s2k.go
new file mode 100644
index 0000000..f369d7e
--- /dev/null
+++ b/libgo/go/crypto/openpgp/s2k/s2k.go
@@ -0,0 +1,146 @@
+// 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.
+
+// This package implements the various OpenPGP string-to-key transforms as
+// specified in RFC 4800 section 3.7.1.
+package s2k
+
+import (
+ "crypto/md5"
+ "crypto/openpgp/error"
+ "crypto/ripemd160"
+ "crypto/sha1"
+ "crypto/sha256"
+ "crypto/sha512"
+ "hash"
+ "io"
+ "os"
+)
+
+// Simple writes to out the result of computing the Simple S2K function (RFC
+// 4880, section 3.7.1.1) using the given hash and input passphrase.
+func Simple(out []byte, h hash.Hash, in []byte) {
+ Salted(out, h, in, nil)
+}
+
+var zero [1]byte
+
+// Salted writes to out the result of computing the Salted S2K function (RFC
+// 4880, section 3.7.1.2) using the given hash, input passphrase and salt.
+func Salted(out []byte, h hash.Hash, in []byte, salt []byte) {
+ done := 0
+
+ for i := 0; done < len(out); i++ {
+ h.Reset()
+ for j := 0; j < i; j++ {
+ h.Write(zero[:])
+ }
+ h.Write(salt)
+ h.Write(in)
+ n := copy(out[done:], h.Sum())
+ done += n
+ }
+}
+
+// Iterated writes to out the result of computing the Iterated and Salted S2K
+// function (RFC 4880, section 3.7.1.3) using the given hash, input passphrase,
+// salt and iteration count.
+func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) {
+ combined := make([]byte, len(in)+len(salt))
+ copy(combined, salt)
+ copy(combined[len(salt):], in)
+
+ if count < len(combined) {
+ count = len(combined)
+ }
+
+ done := 0
+ for i := 0; done < len(out); i++ {
+ h.Reset()
+ for j := 0; j < i; j++ {
+ h.Write(zero[:])
+ }
+ written := 0
+ for written < count {
+ if written+len(combined) > count {
+ todo := count - written
+ h.Write(combined[:todo])
+ written = count
+ } else {
+ h.Write(combined)
+ written += len(combined)
+ }
+ }
+ n := copy(out[done:], h.Sum())
+ done += n
+ }
+}
+
+// Parse reads a binary specification for a string-to-key transformation from r
+// and returns a function which performs that transform.
+func Parse(r io.Reader) (f func(out, in []byte), err os.Error) {
+ var buf [9]byte
+
+ _, err = io.ReadFull(r, buf[:2])
+ if err != nil {
+ return
+ }
+
+ h := hashFuncFromType(buf[1])
+ if h == nil {
+ return nil, error.UnsupportedError("hash for S2K function")
+ }
+
+ switch buf[0] {
+ case 1:
+ f := func(out, in []byte) {
+ Simple(out, h, in)
+ }
+ return f, nil
+ case 2:
+ _, err := io.ReadFull(r, buf[:8])
+ if err != nil {
+ return
+ }
+ f := func(out, in []byte) {
+ Salted(out, h, in, buf[:8])
+ }
+ return f, nil
+ case 3:
+ _, err := io.ReadFull(r, buf[:9])
+ if err != nil {
+ return
+ }
+ count := (16 + int(buf[8]&15)) << (uint32(buf[8]>>4) + 6)
+ f := func(out, in []byte) {
+ Iterated(out, h, in, buf[:8], count)
+ }
+ return f, nil
+ }
+
+ return nil, error.UnsupportedError("S2K function")
+}
+
+// hashFuncFromType returns a hash.Hash which corresponds to the given hash
+// type byte. See RFC 4880, section 9.4.
+func hashFuncFromType(hashType byte) hash.Hash {
+ switch hashType {
+ case 1:
+ return md5.New()
+ case 2:
+ return sha1.New()
+ case 3:
+ return ripemd160.New()
+ case 8:
+ return sha256.New()
+ case 9:
+ return sha512.New384()
+ case 10:
+ return sha512.New()
+ case 11:
+ return sha256.New224()
+ }
+
+ return nil
+}
diff --git a/libgo/go/crypto/openpgp/s2k/s2k_test.go b/libgo/go/crypto/openpgp/s2k/s2k_test.go
new file mode 100644
index 0000000..814b786
--- /dev/null
+++ b/libgo/go/crypto/openpgp/s2k/s2k_test.go
@@ -0,0 +1,94 @@
+// 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 s2k
+
+import (
+ "bytes"
+ "crypto/sha1"
+ "encoding/hex"
+ "testing"
+)
+
+var saltedTests = []struct {
+ in, out string
+}{
+ {"hello", "10295ac1"},
+ {"world", "ac587a5e"},
+ {"foo", "4dda8077"},
+ {"bar", "bd8aac6b9ea9cae04eae6a91c6133b58b5d9a61c14f355516ed9370456"},
+ {"x", "f1d3f289"},
+ {"xxxxxxxxxxxxxxxxxxxxxxx", "e00d7b45"},
+}
+
+func TestSalted(t *testing.T) {
+ h := sha1.New()
+ salt := [4]byte{1, 2, 3, 4}
+
+ for i, test := range saltedTests {
+ expected, _ := hex.DecodeString(test.out)
+ out := make([]byte, len(expected))
+ Salted(out, h, []byte(test.in), salt[:])
+ if !bytes.Equal(expected, out) {
+ t.Errorf("#%d, got: %x want: %x", i, out, expected)
+ }
+ }
+}
+
+
+var iteratedTests = []struct {
+ in, out string
+}{
+ {"hello", "83126105"},
+ {"world", "6fa317f9"},
+ {"foo", "8fbc35b9"},
+ {"bar", "2af5a99b54f093789fd657f19bd245af7604d0f6ae06f66602a46a08ae"},
+ {"x", "5a684dfe"},
+ {"xxxxxxxxxxxxxxxxxxxxxxx", "18955174"},
+}
+
+func TestIterated(t *testing.T) {
+ h := sha1.New()
+ salt := [4]byte{4, 3, 2, 1}
+
+ for i, test := range iteratedTests {
+ expected, _ := hex.DecodeString(test.out)
+ out := make([]byte, len(expected))
+ Iterated(out, h, []byte(test.in), salt[:], 31)
+ if !bytes.Equal(expected, out) {
+ t.Errorf("#%d, got: %x want: %x", i, out, expected)
+ }
+ }
+}
+
+
+var parseTests = []struct {
+ spec, in, out string
+}{
+ /* Simple with SHA1 */
+ {"0102", "hello", "aaf4c61d"},
+ /* Salted with SHA1 */
+ {"02020102030405060708", "hello", "f4f7d67e"},
+ /* Iterated with SHA1 */
+ {"03020102030405060708f1", "hello", "f2a57b7c"},
+}
+
+func TestParse(t *testing.T) {
+ for i, test := range parseTests {
+ spec, _ := hex.DecodeString(test.spec)
+ buf := bytes.NewBuffer(spec)
+ f, err := Parse(buf)
+ if err != nil {
+ t.Errorf("%d: Parse returned error: %s", i, err)
+ continue
+ }
+
+ expected, _ := hex.DecodeString(test.out)
+ out := make([]byte, len(expected))
+ f(out, []byte(test.in))
+ if !bytes.Equal(out, expected) {
+ t.Errorf("%d: output got: %x want: %x", i, out, expected)
+ }
+ }
+}
diff --git a/libgo/go/crypto/rc4/rc4.go b/libgo/go/crypto/rc4/rc4.go
index e47a015..65fd195 100644
--- a/libgo/go/crypto/rc4/rc4.go
+++ b/libgo/go/crypto/rc4/rc4.go
@@ -45,14 +45,14 @@ func NewCipher(key []byte) (*Cipher, os.Error) {
return &c, nil
}
-// XORKeyStream will XOR each byte of the given buffer with a byte of the
-// generated keystream.
-func (c *Cipher) XORKeyStream(buf []byte) {
- for i := range buf {
+// 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]
- buf[i] ^= c.s[c.s[c.i]+c.s[c.j]]
+ dst[i] = src[i] ^ c.s[c.s[c.i]+c.s[c.j]]
}
}
diff --git a/libgo/go/crypto/rc4/rc4_test.go b/libgo/go/crypto/rc4/rc4_test.go
index 73a52e7..6265d94 100644
--- a/libgo/go/crypto/rc4/rc4_test.go
+++ b/libgo/go/crypto/rc4/rc4_test.go
@@ -48,7 +48,7 @@ func TestGolden(t *testing.T) {
return
}
keystream := make([]byte, len(g.keystream))
- c.XORKeyStream(keystream)
+ c.XORKeyStream(keystream, keystream)
for j, v := range keystream {
if g.keystream[j] != v {
t.Errorf("Failed at golden index %d", i)
diff --git a/libgo/go/crypto/rsa/pkcs1v15.go b/libgo/go/crypto/rsa/pkcs1v15.go
index f918d63..7140462 100644
--- a/libgo/go/crypto/rsa/pkcs1v15.go
+++ b/libgo/go/crypto/rsa/pkcs1v15.go
@@ -130,6 +130,9 @@ func nonZeroRandomBytes(s []byte, rand io.Reader) (err os.Error) {
if err != nil {
return
}
+ // In tests, the PRNG may return all zeros so we do
+ // this to break the loop.
+ s[i] ^= 0x42
}
}
diff --git a/libgo/go/crypto/tls/ca_set.go b/libgo/go/crypto/tls/ca_set.go
index fe2a540..ae00ac5 100644
--- a/libgo/go/crypto/tls/ca_set.go
+++ b/libgo/go/crypto/tls/ca_set.go
@@ -16,6 +16,7 @@ type CASet struct {
byName map[string][]*x509.Certificate
}
+// NewCASet returns a new, empty CASet.
func NewCASet() *CASet {
return &CASet{
make(map[string][]*x509.Certificate),
diff --git a/libgo/go/crypto/tls/cipher_suites.go b/libgo/go/crypto/tls/cipher_suites.go
new file mode 100644
index 0000000..bc7b0d3
--- /dev/null
+++ b/libgo/go/crypto/tls/cipher_suites.go
@@ -0,0 +1,102 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tls
+
+import (
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/hmac"
+ "crypto/rc4"
+ "crypto/x509"
+ "hash"
+ "os"
+)
+
+// a keyAgreement implements the client and server side of a TLS key agreement
+// protocol by generating and processing key exchange messages.
+type keyAgreement interface {
+ // On the server side, the first two methods are called in order.
+
+ // In the case that the key agreement protocol doesn't use a
+ // ServerKeyExchange message, generateServerKeyExchange can return nil,
+ // nil.
+ generateServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, os.Error)
+ processClientKeyExchange(*Config, *clientKeyExchangeMsg) ([]byte, os.Error)
+
+ // On the client side, the next two methods are called in order.
+
+ // This method may not be called if the server doesn't send a
+ // ServerKeyExchange message.
+ processServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg, *x509.Certificate, *serverKeyExchangeMsg) os.Error
+ generateClientKeyExchange(*Config, *clientHelloMsg, *x509.Certificate) ([]byte, *clientKeyExchangeMsg, os.Error)
+}
+
+// A cipherSuite is a specific combination of key agreement, cipher and MAC
+// function. All cipher suites currently assume RSA key agreement.
+type cipherSuite struct {
+ // the lengths, in bytes, of the key material needed for each component.
+ keyLen int
+ macLen int
+ ivLen int
+ ka func() keyAgreement
+ // If elliptic is set, a server will only consider this ciphersuite if
+ // the ClientHello indicated that the client supports an elliptic curve
+ // and point format that we can handle.
+ elliptic bool
+ cipher func(key, iv []byte, isRead bool) interface{}
+ mac func(macKey []byte) hash.Hash
+}
+
+var cipherSuites = map[uint16]*cipherSuite{
+ TLS_RSA_WITH_RC4_128_SHA: &cipherSuite{16, 20, 0, rsaKA, false, cipherRC4, hmacSHA1},
+ TLS_RSA_WITH_AES_128_CBC_SHA: &cipherSuite{16, 20, 16, rsaKA, false, cipherAES, hmacSHA1},
+ TLS_ECDHE_RSA_WITH_RC4_128_SHA: &cipherSuite{16, 20, 0, ecdheRSAKA, true, cipherRC4, hmacSHA1},
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: &cipherSuite{16, 20, 16, ecdheRSAKA, true, cipherAES, hmacSHA1},
+}
+
+func cipherRC4(key, iv []byte, isRead bool) interface{} {
+ cipher, _ := rc4.NewCipher(key)
+ return cipher
+}
+
+func cipherAES(key, iv []byte, isRead bool) interface{} {
+ block, _ := aes.NewCipher(key)
+ if isRead {
+ return cipher.NewCBCDecrypter(block, iv)
+ }
+ return cipher.NewCBCEncrypter(block, iv)
+}
+
+func hmacSHA1(key []byte) hash.Hash {
+ return hmac.NewSHA1(key)
+}
+
+func rsaKA() keyAgreement {
+ return rsaKeyAgreement{}
+}
+
+func ecdheRSAKA() keyAgreement {
+ return new(ecdheRSAKeyAgreement)
+}
+
+// mutualCipherSuite returns a cipherSuite and its id given a list of supported
+// ciphersuites and the id requested by the peer.
+func mutualCipherSuite(have []uint16, want uint16) (suite *cipherSuite, id uint16) {
+ for _, id := range have {
+ if id == want {
+ return cipherSuites[id], id
+ }
+ }
+ return
+}
+
+// A list of the possible cipher suite ids. Taken from
+// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
+const (
+ TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005
+ TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f
+ TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xc011
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013
+)
diff --git a/libgo/go/crypto/tls/common.go b/libgo/go/crypto/tls/common.go
index a4f2b80..7135f3d 100644
--- a/libgo/go/crypto/tls/common.go
+++ b/libgo/go/crypto/tls/common.go
@@ -20,7 +20,7 @@ const (
maxHandshake = 65536 // maximum handshake we support (protocol max is 16 MB)
minVersion = 0x0301 // minimum supported version - TLS 1.0
- maxVersion = 0x0302 // maximum supported version - TLS 1.1
+ maxVersion = 0x0301 // maximum supported version - TLS 1.0
)
// TLS record types.
@@ -38,6 +38,7 @@ const (
typeClientHello uint8 = 1
typeServerHello uint8 = 2
typeCertificate uint8 = 11
+ typeServerKeyExchange uint8 = 12
typeCertificateRequest uint8 = 13
typeServerHelloDone uint8 = 14
typeCertificateVerify uint8 = 15
@@ -47,11 +48,6 @@ const (
typeNextProtocol uint8 = 67 // Not IANA assigned
)
-// TLS cipher suites.
-const (
- TLS_RSA_WITH_RC4_128_SHA uint16 = 5
-)
-
// TLS compression types.
const (
compressionNone uint8 = 0
@@ -59,9 +55,25 @@ const (
// TLS extension numbers
var (
- extensionServerName uint16 = 0
- extensionStatusRequest uint16 = 5
- extensionNextProtoNeg uint16 = 13172 // not IANA assigned
+ extensionServerName uint16 = 0
+ extensionStatusRequest uint16 = 5
+ extensionSupportedCurves uint16 = 10
+ extensionSupportedPoints uint16 = 11
+ extensionNextProtoNeg uint16 = 13172 // not IANA assigned
+)
+
+// TLS Elliptic Curves
+// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8
+var (
+ curveP256 uint16 = 23
+ curveP384 uint16 = 24
+ curveP521 uint16 = 25
+)
+
+// TLS Elliptic Curve Point Formats
+// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9
+var (
+ pointFormatUncompressed uint8 = 0
)
// TLS CertificateStatusType (RFC 3546)
@@ -78,6 +90,7 @@ const (
// Rest of these are reserved by the TLS spec
)
+// ConnectionState records basic TLS details about the connection.
type ConnectionState struct {
HandshakeComplete bool
CipherSuite uint16
@@ -88,28 +101,77 @@ type ConnectionState struct {
// has been passed to a TLS function it must not be modified.
type Config struct {
// Rand provides the source of entropy for nonces and RSA blinding.
+ // If Rand is nil, TLS uses the cryptographic random reader in package
+ // crypto/rand.
Rand io.Reader
+
// Time returns the current time as the number of seconds since the epoch.
+ // If Time is nil, TLS uses the system time.Seconds.
Time func() int64
- // Certificates contains one or more certificate chains.
+
+ // Certificates contains one or more certificate chains
+ // to present to the other side of the connection.
+ // Server configurations must include at least one certificate.
Certificates []Certificate
- RootCAs *CASet
+
+ // RootCAs defines the set of root certificate authorities
+ // that clients use when verifying server certificates.
+ // If RootCAs is nil, TLS uses the host's root CA set.
+ RootCAs *CASet
+
// NextProtos is a list of supported, application level protocols.
// Currently only server-side handling is supported.
NextProtos []string
+
// ServerName is included in the client's handshake to support virtual
// hosting.
ServerName string
- // AuthenticateClient determines if a server will request a certificate
+
+ // AuthenticateClient controls whether a server will request a certificate
// from the client. It does not require that the client send a
- // certificate nor, if it does, that the certificate is anything more
- // than self-signed.
+ // certificate nor does it require that the certificate sent be
+ // anything more than self-signed.
AuthenticateClient bool
+
+ // CipherSuites is a list of supported cipher suites. If CipherSuites
+ // is nil, TLS uses a list of suites supported by the implementation.
+ CipherSuites []uint16
+}
+
+func (c *Config) rand() io.Reader {
+ r := c.Rand
+ if r == nil {
+ return rand.Reader
+ }
+ return r
+}
+
+func (c *Config) time() int64 {
+ t := c.Time
+ if t == nil {
+ t = time.Seconds
+ }
+ return t()
}
+func (c *Config) rootCAs() *CASet {
+ s := c.RootCAs
+ if s == nil {
+ s = defaultRoots()
+ }
+ return s
+}
+
+func (c *Config) cipherSuites() []uint16 {
+ s := c.CipherSuites
+ if s == nil {
+ s = defaultCipherSuites()
+ }
+ return s
+}
+
+// A Certificate is a chain of one or more certificates, leaf first.
type Certificate struct {
- // Certificate contains a chain of one or more certificates. Leaf
- // certificate first.
Certificate [][]byte
PrivateKey *rsa.PrivateKey
}
@@ -126,11 +188,6 @@ type handshakeMessage interface {
unmarshal([]byte) bool
}
-type encryptor interface {
- // XORKeyStream xors the contents of the slice with bytes from the key stream.
- XORKeyStream(buf []byte)
-}
-
// mutualVersion returns the protocol version to use given the advertised
// version of the peer.
func mutualVersion(vers uint16) (uint16, bool) {
@@ -143,14 +200,10 @@ func mutualVersion(vers uint16) (uint16, bool) {
return vers, true
}
-// The defaultConfig is used in place of a nil *Config in the TLS server and client.
-var varDefaultConfig *Config
-
-var once sync.Once
+var emptyConfig Config
func defaultConfig() *Config {
- once.Do(initDefaultConfig)
- return varDefaultConfig
+ return &emptyConfig
}
// Possible certificate files; stop after finding one.
@@ -162,7 +215,26 @@ var certFiles = []string{
"/usr/share/curl/curl-ca-bundle.crt", // OS X
}
-func initDefaultConfig() {
+var once sync.Once
+
+func defaultRoots() *CASet {
+ once.Do(initDefaults)
+ return varDefaultRoots
+}
+
+func defaultCipherSuites() []uint16 {
+ once.Do(initDefaults)
+ return varDefaultCipherSuites
+}
+
+func initDefaults() {
+ initDefaultRoots()
+ initDefaultCipherSuites()
+}
+
+var varDefaultRoots *CASet
+
+func initDefaultRoots() {
roots := NewCASet()
for _, file := range certFiles {
data, err := ioutil.ReadFile(file)
@@ -171,10 +243,16 @@ func initDefaultConfig() {
break
}
}
+ varDefaultRoots = roots
+}
+
+var varDefaultCipherSuites []uint16
- varDefaultConfig = &Config{
- Rand: rand.Reader,
- Time: time.Seconds,
- RootCAs: roots,
+func initDefaultCipherSuites() {
+ varDefaultCipherSuites = make([]uint16, len(cipherSuites))
+ i := 0
+ for id, _ := range cipherSuites {
+ varDefaultCipherSuites[i] = id
+ i++
}
}
diff --git a/libgo/go/crypto/tls/conn.go b/libgo/go/crypto/tls/conn.go
index b18cda7..d203e8d 100644
--- a/libgo/go/crypto/tls/conn.go
+++ b/libgo/go/crypto/tls/conn.go
@@ -1,9 +1,14 @@
+// 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.
+
// TLS low level connection and record layer
package tls
import (
"bytes"
+ "crypto/cipher"
"crypto/subtle"
"crypto/x509"
"hash"
@@ -99,31 +104,31 @@ func (c *Conn) SetWriteTimeout(nsec int64) os.Error {
// connection, either sending or receiving.
type halfConn struct {
sync.Mutex
- crypt encryptor // encryption state
- mac hash.Hash // MAC algorithm
- seq [8]byte // 64-bit sequence number
- bfree *block // list of free blocks
+ cipher interface{} // cipher algorithm
+ mac hash.Hash // MAC algorithm
+ seq [8]byte // 64-bit sequence number
+ bfree *block // list of free blocks
- nextCrypt encryptor // next encryption state
- nextMac hash.Hash // next MAC algorithm
+ nextCipher interface{} // next encryption state
+ nextMac hash.Hash // next MAC algorithm
}
// prepareCipherSpec sets the encryption and MAC states
// that a subsequent changeCipherSpec will use.
-func (hc *halfConn) prepareCipherSpec(crypt encryptor, mac hash.Hash) {
- hc.nextCrypt = crypt
+func (hc *halfConn) prepareCipherSpec(cipher interface{}, mac hash.Hash) {
+ hc.nextCipher = cipher
hc.nextMac = mac
}
// changeCipherSpec changes the encryption and MAC states
// to the ones previously passed to prepareCipherSpec.
func (hc *halfConn) changeCipherSpec() os.Error {
- if hc.nextCrypt == nil {
+ if hc.nextCipher == nil {
return alertInternalError
}
- hc.crypt = hc.nextCrypt
+ hc.cipher = hc.nextCipher
hc.mac = hc.nextMac
- hc.nextCrypt = nil
+ hc.nextCipher = nil
hc.nextMac = nil
return nil
}
@@ -150,27 +155,102 @@ func (hc *halfConn) resetSeq() {
}
}
+// removePadding returns an unpadded slice, in constant time, which is a prefix
+// of the input. It also returns a byte which is equal to 255 if the padding
+// was valid and 0 otherwise. See RFC 2246, section 6.2.3.2
+func removePadding(payload []byte) ([]byte, byte) {
+ if len(payload) < 1 {
+ return payload, 0
+ }
+
+ paddingLen := payload[len(payload)-1]
+ t := uint(len(payload)-1) - uint(paddingLen)
+ // if len(payload) >= (paddingLen - 1) then the MSB of t is zero
+ good := byte(int32(^t) >> 31)
+
+ toCheck := 255 // the maximum possible padding length
+ // The length of the padded data is public, so we can use an if here
+ if toCheck+1 > len(payload) {
+ toCheck = len(payload) - 1
+ }
+
+ for i := 0; i < toCheck; i++ {
+ t := uint(paddingLen) - uint(i)
+ // if i <= paddingLen then the MSB of t is zero
+ mask := byte(int32(^t) >> 31)
+ b := payload[len(payload)-1-i]
+ good &^= mask&paddingLen ^ mask&b
+ }
+
+ // We AND together the bits of good and replicate the result across
+ // all the bits.
+ good &= good << 4
+ good &= good << 2
+ good &= good << 1
+ good = uint8(int8(good) >> 7)
+
+ toRemove := good&paddingLen + 1
+ return payload[:len(payload)-int(toRemove)], good
+}
+
+func roundUp(a, b int) int {
+ return a + (b-a%b)%b
+}
+
// decrypt checks and strips the mac and decrypts the data in b.
func (hc *halfConn) decrypt(b *block) (bool, alert) {
// pull out payload
payload := b.data[recordHeaderLen:]
+ macSize := 0
+ if hc.mac != nil {
+ macSize = hc.mac.Size()
+ }
+
+ paddingGood := byte(255)
+
// decrypt
- if hc.crypt != nil {
- hc.crypt.XORKeyStream(payload)
+ if hc.cipher != nil {
+ switch c := hc.cipher.(type) {
+ case cipher.Stream:
+ c.XORKeyStream(payload, payload)
+ case cipher.BlockMode:
+ blockSize := c.BlockSize()
+
+ if len(payload)%blockSize != 0 || len(payload) < roundUp(macSize+1, blockSize) {
+ return false, alertBadRecordMAC
+ }
+
+ c.CryptBlocks(payload, payload)
+ payload, paddingGood = removePadding(payload)
+ b.resize(recordHeaderLen + len(payload))
+
+ // note that we still have a timing side-channel in the
+ // MAC check, below. An attacker can align the record
+ // so that a correct padding will cause one less hash
+ // block to be calculated. Then they can iteratively
+ // decrypt a record by breaking each byte. See
+ // "Password Interception in a SSL/TLS Channel", Brice
+ // Canvel et al.
+ //
+ // However, our behaviour matches OpenSSL, so we leak
+ // only as much as they do.
+ default:
+ panic("unknown cipher type")
+ }
}
// check, strip mac
if hc.mac != nil {
- if len(payload) < hc.mac.Size() {
+ if len(payload) < macSize {
return false, alertBadRecordMAC
}
// strip mac off payload, b.data
- n := len(payload) - hc.mac.Size()
+ n := len(payload) - macSize
b.data[3] = byte(n >> 8)
b.data[4] = byte(n)
- b.data = b.data[0 : recordHeaderLen+n]
+ b.resize(recordHeaderLen + n)
remoteMAC := payload[n:]
hc.mac.Reset()
@@ -178,7 +258,7 @@ func (hc *halfConn) decrypt(b *block) (bool, alert) {
hc.incSeq()
hc.mac.Write(b.data)
- if subtle.ConstantTimeCompare(hc.mac.Sum(), remoteMAC) != 1 {
+ if subtle.ConstantTimeCompare(hc.mac.Sum(), remoteMAC) != 1 || paddingGood != 255 {
return false, alertBadRecordMAC
}
}
@@ -186,6 +266,23 @@ func (hc *halfConn) decrypt(b *block) (bool, alert) {
return true, 0
}
+// padToBlockSize calculates the needed padding block, if any, for a payload.
+// On exit, prefix aliases payload and extends to the end of the last full
+// block of payload. finalBlock is a fresh slice which contains the contents of
+// any suffix of payload as well as the needed padding to make finalBlock a
+// full block.
+func padToBlockSize(payload []byte, blockSize int) (prefix, finalBlock []byte) {
+ overrun := len(payload) % blockSize
+ paddingLen := blockSize - overrun
+ prefix = payload[:len(payload)-overrun]
+ finalBlock = make([]byte, blockSize)
+ copy(finalBlock, payload[len(payload)-overrun:])
+ for i := overrun; i < blockSize; i++ {
+ finalBlock[i] = byte(paddingLen - 1)
+ }
+ return
+}
+
// encrypt encrypts and macs the data in b.
func (hc *halfConn) encrypt(b *block) (bool, alert) {
// mac
@@ -198,18 +295,30 @@ func (hc *halfConn) encrypt(b *block) (bool, alert) {
n := len(b.data)
b.resize(n + len(mac))
copy(b.data[n:], mac)
-
- // update length to include mac
- n = len(b.data) - recordHeaderLen
- b.data[3] = byte(n >> 8)
- b.data[4] = byte(n)
}
+ payload := b.data[recordHeaderLen:]
+
// encrypt
- if hc.crypt != nil {
- hc.crypt.XORKeyStream(b.data[recordHeaderLen:])
+ if hc.cipher != nil {
+ switch c := hc.cipher.(type) {
+ case cipher.Stream:
+ c.XORKeyStream(payload, payload)
+ case cipher.BlockMode:
+ prefix, finalBlock := padToBlockSize(payload, c.BlockSize())
+ b.resize(recordHeaderLen + len(prefix) + len(finalBlock))
+ c.CryptBlocks(b.data[recordHeaderLen:], prefix)
+ c.CryptBlocks(b.data[recordHeaderLen+len(prefix):], finalBlock)
+ default:
+ panic("unknown cipher type")
+ }
}
+ // update length to include MAC and any block padding needed.
+ n := len(b.data) - recordHeaderLen
+ b.data[3] = byte(n >> 8)
+ b.data[4] = byte(n)
+
return true, 0
}
@@ -542,6 +651,8 @@ func (c *Conn) readHandshake() (interface{}, os.Error) {
m = new(certificateRequestMsg)
case typeCertificateStatus:
m = new(certificateStatusMsg)
+ case typeServerKeyExchange:
+ m = new(serverKeyExchangeMsg)
case typeServerHelloDone:
m = new(serverHelloDoneMsg)
case typeClientKeyExchange:
@@ -560,7 +671,7 @@ func (c *Conn) readHandshake() (interface{}, os.Error) {
// The handshake message unmarshallers
// expect to be able to keep references to data,
// so pass in a fresh copy that won't be overwritten.
- data = bytes.Add(nil, data)
+ data = append([]byte(nil), data...)
if !m.unmarshal(data) {
c.sendAlert(alertUnexpectedMessage)
diff --git a/libgo/go/crypto/tls/conn_test.go b/libgo/go/crypto/tls/conn_test.go
new file mode 100644
index 0000000..f44a50b
--- /dev/null
+++ b/libgo/go/crypto/tls/conn_test.go
@@ -0,0 +1,52 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tls
+
+import (
+ "testing"
+)
+
+func TestRoundUp(t *testing.T) {
+ if roundUp(0, 16) != 0 ||
+ roundUp(1, 16) != 16 ||
+ roundUp(15, 16) != 16 ||
+ roundUp(16, 16) != 16 ||
+ roundUp(17, 16) != 32 {
+ t.Error("roundUp broken")
+ }
+}
+
+var paddingTests = []struct {
+ in []byte
+ good bool
+ expectedLen int
+}{
+ {[]byte{1, 2, 3, 4, 0}, true, 4},
+ {[]byte{1, 2, 3, 4, 0, 1}, false, 0},
+ {[]byte{1, 2, 3, 4, 99, 99}, false, 0},
+ {[]byte{1, 2, 3, 4, 1, 1}, true, 4},
+ {[]byte{1, 2, 3, 2, 2, 2}, true, 3},
+ {[]byte{1, 2, 3, 3, 3, 3}, true, 2},
+ {[]byte{1, 2, 3, 4, 3, 3}, false, 0},
+ {[]byte{1, 4, 4, 4, 4, 4}, true, 1},
+ {[]byte{5, 5, 5, 5, 5, 5}, true, 0},
+ {[]byte{6, 6, 6, 6, 6, 6}, false, 0},
+}
+
+func TestRemovePadding(t *testing.T) {
+ for i, test := range paddingTests {
+ payload, good := removePadding(test.in)
+ expectedGood := byte(255)
+ if !test.good {
+ expectedGood = 0
+ }
+ if good != expectedGood {
+ t.Errorf("#%d: wrong validity, want:%d got:%d", i, expectedGood, good)
+ }
+ if good == 255 && len(payload) != test.expectedLen {
+ t.Errorf("#%d: got %d, want %d", i, len(payload), test.expectedLen)
+ }
+ }
+}
diff --git a/libgo/go/crypto/tls/generate_cert.go b/libgo/go/crypto/tls/generate_cert.go
index bdc70f1..3e0c639 100644
--- a/libgo/go/crypto/tls/generate_cert.go
+++ b/libgo/go/crypto/tls/generate_cert.go
@@ -9,6 +9,7 @@ package main
import (
"crypto/rsa"
+ "crypto/rand"
"crypto/x509"
"encoding/pem"
"flag"
@@ -22,13 +23,7 @@ var hostName *string = flag.String("host", "127.0.0.1", "Hostname to generate a
func main() {
flag.Parse()
- urandom, err := os.Open("/dev/urandom", os.O_RDONLY, 0)
- if err != nil {
- log.Exitf("failed to open /dev/urandom: %s", err)
- return
- }
-
- priv, err := rsa.GenerateKey(urandom, 1024)
+ priv, err := rsa.GenerateKey(rand.Reader, 1024)
if err != nil {
log.Exitf("failed to generate private key: %s", err)
return
@@ -40,7 +35,7 @@ func main() {
SerialNumber: []byte{0},
Subject: x509.Name{
CommonName: *hostName,
- Organization: "Acme Co",
+ Organization: []string{"Acme Co"},
},
NotBefore: time.SecondsToUTC(now - 300),
NotAfter: time.SecondsToUTC(now + 60*60*24*365), // valid for 1 year.
@@ -49,7 +44,7 @@ func main() {
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
}
- derBytes, err := x509.CreateCertificate(urandom, &template, &template, &priv.PublicKey, priv)
+ derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
if err != nil {
log.Exitf("Failed to create certificate: %s", err)
return
diff --git a/libgo/go/crypto/tls/handshake_client.go b/libgo/go/crypto/tls/handshake_client.go
index b6b0e0f..1ca33f5 100644
--- a/libgo/go/crypto/tls/handshake_client.go
+++ b/libgo/go/crypto/tls/handshake_client.go
@@ -5,8 +5,6 @@
package tls
import (
- "crypto/hmac"
- "crypto/rc4"
"crypto/rsa"
"crypto/subtle"
"crypto/x509"
@@ -23,19 +21,21 @@ func (c *Conn) clientHandshake() os.Error {
hello := &clientHelloMsg{
vers: maxVersion,
- cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ cipherSuites: c.config.cipherSuites(),
compressionMethods: []uint8{compressionNone},
random: make([]byte, 32),
ocspStapling: true,
serverName: c.config.ServerName,
+ supportedCurves: []uint16{curveP256, curveP384, curveP521},
+ supportedPoints: []uint8{pointFormatUncompressed},
}
- t := uint32(c.config.Time())
+ t := uint32(c.config.time())
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(c.config.Rand, hello.random[4:])
+ _, err := io.ReadFull(c.config.rand(), hello.random[4:])
if err != nil {
c.sendAlert(alertInternalError)
return os.ErrorString("short read from Rand")
@@ -61,11 +61,15 @@ func (c *Conn) clientHandshake() os.Error {
c.vers = vers
c.haveVers = true
- if serverHello.cipherSuite != TLS_RSA_WITH_RC4_128_SHA ||
- serverHello.compressionMethod != compressionNone {
+ if serverHello.compressionMethod != compressionNone {
return c.sendAlert(alertUnexpectedMessage)
}
+ suite, suiteId := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite)
+ if suite == nil {
+ return c.sendAlert(alertHandshakeFailure)
+ }
+
msg, err = c.readHandshake()
if err != nil {
return err
@@ -128,8 +132,7 @@ func (c *Conn) clientHandshake() os.Error {
cur = parent
}
- pub, ok := certs[0].PublicKey.(*rsa.PublicKey)
- if !ok {
+ if _, ok := certs[0].PublicKey.(*rsa.PublicKey); !ok {
return c.sendAlert(alertUnsupportedCertificate)
}
@@ -156,6 +159,23 @@ func (c *Conn) clientHandshake() os.Error {
return err
}
+ keyAgreement := suite.ka()
+
+ skx, ok := msg.(*serverKeyExchangeMsg)
+ if ok {
+ finishedHash.Write(skx.marshal())
+ err = keyAgreement.processServerKeyExchange(c.config, hello, serverHello, certs[0], skx)
+ if err != nil {
+ c.sendAlert(alertUnexpectedMessage)
+ return err
+ }
+
+ msg, err = c.readHandshake()
+ if err != nil {
+ return err
+ }
+ }
+
transmitCert := false
certReq, ok := msg.(*certificateRequestMsg)
if ok {
@@ -213,29 +233,22 @@ func (c *Conn) clientHandshake() os.Error {
c.writeRecord(recordTypeHandshake, certMsg.marshal())
}
- ckx := new(clientKeyExchangeMsg)
- preMasterSecret := make([]byte, 48)
- preMasterSecret[0] = byte(hello.vers >> 8)
- preMasterSecret[1] = byte(hello.vers)
- _, err = io.ReadFull(c.config.Rand, preMasterSecret[2:])
+ preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hello, certs[0])
if err != nil {
- return c.sendAlert(alertInternalError)
+ c.sendAlert(alertInternalError)
+ return err
}
-
- ckx.ciphertext, err = rsa.EncryptPKCS1v15(c.config.Rand, pub, preMasterSecret)
- if err != nil {
- return c.sendAlert(alertInternalError)
+ if ckx != nil {
+ finishedHash.Write(ckx.marshal())
+ c.writeRecord(recordTypeHandshake, ckx.marshal())
}
- finishedHash.Write(ckx.marshal())
- c.writeRecord(recordTypeHandshake, ckx.marshal())
-
if cert != nil {
certVerify := new(certificateVerifyMsg)
var digest [36]byte
copy(digest[0:16], finishedHash.serverMD5.Sum())
copy(digest[16:36], finishedHash.serverSHA1.Sum())
- signed, err := rsa.SignPKCS1v15(c.config.Rand, c.config.Certificates[0].PrivateKey, rsa.HashMD5SHA1, digest[0:])
+ signed, err := rsa.SignPKCS1v15(c.config.rand(), c.config.Certificates[0].PrivateKey, rsa.HashMD5SHA1, digest[0:])
if err != nil {
return c.sendAlert(alertInternalError)
}
@@ -245,13 +258,12 @@ func (c *Conn) clientHandshake() os.Error {
c.writeRecord(recordTypeHandshake, certVerify.marshal())
}
- suite := cipherSuites[0]
- masterSecret, clientMAC, serverMAC, clientKey, serverKey :=
- keysFromPreMasterSecret11(preMasterSecret, hello.random, serverHello.random, suite.hashLength, suite.cipherKeyLength)
-
- cipher, _ := rc4.NewCipher(clientKey)
+ masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
+ keysFromPreMasterSecret10(preMasterSecret, hello.random, serverHello.random, suite.macLen, suite.keyLen, suite.ivLen)
- c.out.prepareCipherSpec(cipher, hmac.NewSHA1(clientMAC))
+ clientCipher := suite.cipher(clientKey, clientIV, false /* not for reading */ )
+ clientHash := suite.mac(clientMAC)
+ c.out.prepareCipherSpec(clientCipher, clientHash)
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
finished := new(finishedMsg)
@@ -259,8 +271,9 @@ func (c *Conn) clientHandshake() os.Error {
finishedHash.Write(finished.marshal())
c.writeRecord(recordTypeHandshake, finished.marshal())
- cipher2, _ := rc4.NewCipher(serverKey)
- c.in.prepareCipherSpec(cipher2, hmac.NewSHA1(serverMAC))
+ serverCipher := suite.cipher(serverKey, serverIV, true /* for reading */ )
+ serverHash := suite.mac(serverMAC)
+ c.in.prepareCipherSpec(serverCipher, serverHash)
c.readRecord(recordTypeChangeCipherSpec)
if c.err != nil {
return c.err
@@ -282,6 +295,6 @@ func (c *Conn) clientHandshake() os.Error {
}
c.handshakeComplete = true
- c.cipherSuite = TLS_RSA_WITH_RC4_128_SHA
+ c.cipherSuite = suiteId
return nil
}
diff --git a/libgo/go/crypto/tls/handshake_client_test.go b/libgo/go/crypto/tls/handshake_client_test.go
new file mode 100644
index 0000000..e5c9684
--- /dev/null
+++ b/libgo/go/crypto/tls/handshake_client_test.go
@@ -0,0 +1,211 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tls
+
+import (
+ "bytes"
+ "flag"
+ "io"
+ "net"
+ "testing"
+)
+
+func testClientScript(t *testing.T, name string, clientScript [][]byte, config *Config) {
+ c, s := net.Pipe()
+ cli := Client(c, config)
+ go func() {
+ cli.Write([]byte("hello\n"))
+ cli.Close()
+ }()
+
+ defer c.Close()
+ for i, b := range clientScript {
+ if i%2 == 1 {
+ s.Write(b)
+ continue
+ }
+ bb := make([]byte, len(b))
+ _, err := io.ReadFull(s, bb)
+ if err != nil {
+ t.Fatalf("%s #%d: %s", name, i, err)
+ }
+ if !bytes.Equal(b, bb) {
+ t.Fatalf("%s #%d: mismatch on read: got:%x want:%x", name, i, bb, b)
+ }
+ }
+}
+
+func TestHandshakeClientRC4(t *testing.T) {
+ testClientScript(t, "RC4", rc4ClientScript, testConfig)
+}
+
+var connect = flag.Bool("connect", false, "connect to a TLS server on :10443")
+
+func TestRunClient(t *testing.T) {
+ if !*connect {
+ return
+ }
+
+ testConfig.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA}
+
+ conn, err := Dial("tcp", "", "127.0.0.1:10443", testConfig)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ conn.Write([]byte("hello\n"))
+ conn.Close()
+}
+
+// Script of interaction with gnutls implementation.
+// The values for this test are obtained by building and running in client mode:
+// % gotest -match "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
+//
+// Where key.pem is:
+// -----BEGIN RSA PRIVATE KEY-----
+// MIIBPAIBAAJBAJ+zw4Qnlf8SMVIPFe9GEcStgOY2Ww/dgNdhjeD8ckUJNP5VZkVD
+// TGiXav6ooKXfX3j/7tdkuD8Ey2//Kv7+ue0CAwEAAQJAN6W31vDEP2DjdqhzCDDu
+// OA4NACqoiFqyblo7yc2tM4h4xMbC3Yx5UKMN9ZkCtX0gzrz6DyF47bdKcWBzNWCj
+// gQIhANEoojVt7hq+SQ6MCN6FTAysGgQf56Q3TYoJMoWvdiXVAiEAw3e3rc+VJpOz
+// rHuDo6bgpjUAAXM+v3fcpsfZSNO6V7kCIQCtbVjanpUwvZkMI9by02oUk9taki3b
+// PzPfAfNPYAbCJQIhAJXNQDWyqwn/lGmR11cqY2y9nZ1+5w3yHGatLrcDnQHxAiEA
+// vnlEGo8K85u+KwIOimM48ZG8oTk7iFdkqLJR1utT3aU=
+// -----END RSA PRIVATE KEY-----
+//
+// and cert.pem is:
+// -----BEGIN CERTIFICATE-----
+// MIIBoDCCAUoCAQAwDQYJKoZIhvcNAQEEBQAwYzELMAkGA1UEBhMCQVUxEzARBgNV
+// BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMSMwIQYD
+// VQQDExpTZXJ2ZXIgdGVzdCBjZXJ0ICg1MTIgYml0KTAeFw05NzA5MDkwMzQxMjZa
+// Fw05NzEwMDkwMzQxMjZaMF4xCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0
+// YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxFzAVBgNVBAMT
+// DkVyaWMgdGhlIFlvdW5nMFEwCQYFKw4DAgwFAANEAAJBALVEqPODnpI4rShlY8S7
+// tB713JNvabvn6Gned7zylwLLiXQAo/PAT6mfdWPTyCX9RlId/Aroh1ou893BA32Q
+// sggwDQYJKoZIhvcNAQEEBQADQQCU5SSgapJSdRXJoX+CpCvFy+JVh9HpSjCpSNKO
+// 19raHv98hKAUJuP9HyM+SUsffO6mAIgitUaqW8/wDMePhEC3
+// -----END CERTIFICATE-----
+var rc4ClientScript = [][]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, 0x00, 0x05,
+ 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, 0x4a, 0x02, 0x00, 0x00,
+ 0x46, 0x03, 0x01, 0x4d, 0x0a, 0x56, 0x16, 0xb5,
+ 0x91, 0xd1, 0xcb, 0x80, 0x4d, 0xc7, 0x46, 0xf3,
+ 0x37, 0x0c, 0xef, 0xea, 0x64, 0x11, 0x14, 0x56,
+ 0x97, 0x9b, 0xc5, 0x67, 0x08, 0xb7, 0x13, 0xea,
+ 0xf8, 0xc9, 0xb3, 0x20, 0xe2, 0xfc, 0x41, 0xf6,
+ 0x96, 0x90, 0x9d, 0x43, 0x9b, 0xe9, 0x6e, 0xf8,
+ 0x41, 0x16, 0xcc, 0xf3, 0xc7, 0xde, 0xda, 0x5a,
+ 0xa1, 0x33, 0x69, 0xe2, 0xde, 0x5b, 0xaf, 0x2a,
+ 0x92, 0xe7, 0xd4, 0xa0, 0x00, 0x05, 0x00, 0x16,
+ 0x03, 0x01, 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xf3,
+ 0x00, 0x01, 0xf0, 0x00, 0x01, 0xed, 0x30, 0x82,
+ 0x01, 0xe9, 0x30, 0x82, 0x01, 0x52, 0x02, 0x01,
+ 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00,
+ 0x30, 0x5b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31,
+ 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
+ 0x13, 0x0a, 0x51, 0x75, 0x65, 0x65, 0x6e, 0x73,
+ 0x6c, 0x61, 0x6e, 0x64, 0x31, 0x1a, 0x30, 0x18,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x43,
+ 0x72, 0x79, 0x70, 0x74, 0x53, 0x6f, 0x66, 0x74,
+ 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64,
+ 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x13, 0x12, 0x54, 0x65, 0x73, 0x74, 0x20,
+ 0x43, 0x41, 0x20, 0x28, 0x31, 0x30, 0x32, 0x34,
+ 0x20, 0x62, 0x69, 0x74, 0x29, 0x30, 0x1e, 0x17,
+ 0x0d, 0x30, 0x30, 0x31, 0x30, 0x31, 0x36, 0x32,
+ 0x32, 0x33, 0x31, 0x30, 0x33, 0x5a, 0x17, 0x0d,
+ 0x30, 0x33, 0x30, 0x31, 0x31, 0x34, 0x32, 0x32,
+ 0x33, 0x31, 0x30, 0x33, 0x5a, 0x30, 0x63, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x51,
+ 0x75, 0x65, 0x65, 0x6e, 0x73, 0x6c, 0x61, 0x6e,
+ 0x64, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x11, 0x43, 0x72, 0x79, 0x70,
+ 0x74, 0x53, 0x6f, 0x66, 0x74, 0x20, 0x50, 0x74,
+ 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x23, 0x30,
+ 0x21, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1a,
+ 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x74,
+ 0x65, 0x73, 0x74, 0x20, 0x63, 0x65, 0x72, 0x74,
+ 0x20, 0x28, 0x35, 0x31, 0x32, 0x20, 0x62, 0x69,
+ 0x74, 0x29, 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,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00, 0x03,
+ 0x81, 0x81, 0x00, 0x93, 0xd2, 0x0a, 0xc5, 0x41,
+ 0xe6, 0x5a, 0xa9, 0x86, 0xf9, 0x11, 0x87, 0xe4,
+ 0xdb, 0x45, 0xe2, 0xc5, 0x95, 0x78, 0x1a, 0x6c,
+ 0x80, 0x6d, 0x73, 0x1f, 0xb4, 0x6d, 0x44, 0xa3,
+ 0xba, 0x86, 0x88, 0xc8, 0x58, 0xcd, 0x1c, 0x06,
+ 0x35, 0x6c, 0x44, 0x62, 0x88, 0xdf, 0xe4, 0xf6,
+ 0x64, 0x61, 0x95, 0xef, 0x4a, 0xa6, 0x7f, 0x65,
+ 0x71, 0xd7, 0x6b, 0x88, 0x39, 0xf6, 0x32, 0xbf,
+ 0xac, 0x93, 0x67, 0x69, 0x51, 0x8c, 0x93, 0xec,
+ 0x48, 0x5f, 0xc9, 0xb1, 0x42, 0xf9, 0x55, 0xd2,
+ 0x7e, 0x4e, 0xf4, 0xf2, 0x21, 0x6b, 0x90, 0x57,
+ 0xe6, 0xd7, 0x99, 0x9e, 0x41, 0xca, 0x80, 0xbf,
+ 0x1a, 0x28, 0xa2, 0xca, 0x5b, 0x50, 0x4a, 0xed,
+ 0x84, 0xe7, 0x82, 0xc7, 0xd2, 0xcf, 0x36, 0x9e,
+ 0x6a, 0x67, 0xb9, 0x88, 0xa7, 0xf3, 0x8a, 0xd0,
+ 0x04, 0xf8, 0xe8, 0xc6, 0x17, 0xe3, 0xc5, 0x29,
+ 0xbc, 0x17, 0xf1, 0x16, 0x03, 0x01, 0x00, 0x04,
+ 0x0e, 0x00, 0x00, 0x00,
+ },
+
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x46, 0x10, 0x00, 0x00,
+ 0x42, 0x00, 0x40, 0x87, 0xa1, 0x1f, 0x14, 0xe1,
+ 0xfb, 0x91, 0xac, 0x58, 0x2e, 0xf3, 0x71, 0xce,
+ 0x01, 0x85, 0x2c, 0xc7, 0xfe, 0x84, 0x87, 0x82,
+ 0xb7, 0x57, 0xdb, 0x37, 0x4d, 0x46, 0x83, 0x67,
+ 0x52, 0x82, 0x51, 0x01, 0x95, 0x23, 0x68, 0x69,
+ 0x6b, 0xd0, 0xa7, 0xa7, 0xe5, 0x88, 0xd0, 0x47,
+ 0x71, 0xb8, 0xd2, 0x03, 0x05, 0x25, 0x56, 0x5c,
+ 0x10, 0x08, 0xc6, 0x9b, 0xd4, 0x67, 0xcd, 0x28,
+ 0xbe, 0x9c, 0x48, 0x14, 0x03, 0x01, 0x00, 0x01,
+ 0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xc1, 0xb8,
+ 0xd3, 0x7f, 0xc5, 0xc2, 0x5a, 0x1d, 0x6d, 0x5b,
+ 0x2d, 0x5c, 0x82, 0x87, 0xc2, 0x6f, 0x0d, 0x63,
+ 0x7b, 0x72, 0x2b, 0xda, 0x69, 0xc4, 0xfe, 0x3c,
+ 0x84, 0xa1, 0x5a, 0x62, 0x38, 0x37, 0xc6, 0x54,
+ 0x25, 0x2a,
+ },
+
+ {
+ 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+ 0x01, 0x00, 0x24, 0xea, 0x88, 0x9c, 0x00, 0xf6,
+ 0x35, 0xb8, 0x42, 0x7f, 0x15, 0x17, 0x76, 0x5e,
+ 0x4b, 0x24, 0xcb, 0x7e, 0xa0, 0x7b, 0xc3, 0x70,
+ 0x52, 0x0a, 0x88, 0x2a, 0x7a, 0x45, 0x59, 0x90,
+ 0x59, 0xac, 0xc6, 0xb5, 0x56, 0x55, 0x96,
+ },
+}
diff --git a/libgo/go/crypto/tls/handshake_messages.go b/libgo/go/crypto/tls/handshake_messages.go
index 91771ce..e5e8562 100644
--- a/libgo/go/crypto/tls/handshake_messages.go
+++ b/libgo/go/crypto/tls/handshake_messages.go
@@ -14,6 +14,8 @@ type clientHelloMsg struct {
nextProtoNeg bool
serverName string
ocspStapling bool
+ supportedCurves []uint16
+ supportedPoints []uint8
}
func (m *clientHelloMsg) marshal() []byte {
@@ -35,6 +37,14 @@ func (m *clientHelloMsg) marshal() []byte {
extensionsLength += 5 + len(m.serverName)
numExtensions++
}
+ if len(m.supportedCurves) > 0 {
+ extensionsLength += 2 + 2*len(m.supportedCurves)
+ numExtensions++
+ }
+ if len(m.supportedPoints) > 0 {
+ extensionsLength += 1 + len(m.supportedPoints)
+ numExtensions++
+ }
if numExtensions > 0 {
extensionsLength += 4 * numExtensions
length += 2 + extensionsLength
@@ -117,6 +127,38 @@ func (m *clientHelloMsg) marshal() []byte {
// Two zero valued uint16s for the two lengths.
z = z[9:]
}
+ if len(m.supportedCurves) > 0 {
+ // http://tools.ietf.org/html/rfc4492#section-5.5.1
+ z[0] = byte(extensionSupportedCurves >> 8)
+ z[1] = byte(extensionSupportedCurves)
+ l := 2 + 2*len(m.supportedCurves)
+ z[2] = byte(l >> 8)
+ z[3] = byte(l)
+ l -= 2
+ z[4] = byte(l >> 8)
+ z[5] = byte(l)
+ z = z[6:]
+ for _, curve := range m.supportedCurves {
+ z[0] = byte(curve >> 8)
+ z[1] = byte(curve)
+ z = z[2:]
+ }
+ }
+ if len(m.supportedPoints) > 0 {
+ // http://tools.ietf.org/html/rfc4492#section-5.5.2
+ z[0] = byte(extensionSupportedPoints >> 8)
+ z[1] = byte(extensionSupportedPoints)
+ l := 1 + len(m.supportedPoints)
+ z[2] = byte(l >> 8)
+ z[3] = byte(l)
+ l--
+ z[4] = byte(l)
+ z = z[5:]
+ for _, pointFormat := range m.supportedPoints {
+ z[0] = byte(pointFormat)
+ z = z[1:]
+ }
+ }
m.raw = x
@@ -221,6 +263,33 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
m.nextProtoNeg = true
case extensionStatusRequest:
m.ocspStapling = length > 0 && data[0] == statusTypeOCSP
+ case extensionSupportedCurves:
+ // http://tools.ietf.org/html/rfc4492#section-5.5.1
+ if length < 2 {
+ return false
+ }
+ l := int(data[0])<<8 | int(data[1])
+ if l%2 == 1 || length != l+2 {
+ return false
+ }
+ numCurves := l / 2
+ m.supportedCurves = make([]uint16, numCurves)
+ d := data[2:]
+ for i := 0; i < numCurves; i++ {
+ m.supportedCurves[i] = uint16(d[0])<<8 | uint16(d[1])
+ d = d[2:]
+ }
+ case extensionSupportedPoints:
+ // http://tools.ietf.org/html/rfc4492#section-5.5.2
+ if length < 1 {
+ return false
+ }
+ l := int(data[0])
+ if length != l+1 {
+ return false
+ }
+ m.supportedPoints = make([]uint8, l)
+ copy(m.supportedPoints, data[1:])
}
data = data[length:]
}
@@ -466,6 +535,36 @@ func (m *certificateMsg) unmarshal(data []byte) bool {
return true
}
+type serverKeyExchangeMsg struct {
+ raw []byte
+ key []byte
+}
+
+func (m *serverKeyExchangeMsg) marshal() []byte {
+ if m.raw != nil {
+ return m.raw
+ }
+ length := len(m.key)
+ x := make([]byte, length+4)
+ x[0] = typeServerKeyExchange
+ x[1] = uint8(length >> 16)
+ x[2] = uint8(length >> 8)
+ x[3] = uint8(length)
+ copy(x[4:], m.key)
+
+ m.raw = x
+ return x
+}
+
+func (m *serverKeyExchangeMsg) unmarshal(data []byte) bool {
+ m.raw = data
+ if len(data) < 4 {
+ return false
+ }
+ m.key = data[4:]
+ return true
+}
+
type certificateStatusMsg struct {
raw []byte
statusType uint8
@@ -542,15 +641,13 @@ func (m *clientKeyExchangeMsg) marshal() []byte {
if m.raw != nil {
return m.raw
}
- length := len(m.ciphertext) + 2
+ length := len(m.ciphertext)
x := make([]byte, length+4)
x[0] = typeClientKeyExchange
x[1] = uint8(length >> 16)
x[2] = uint8(length >> 8)
x[3] = uint8(length)
- x[4] = uint8(len(m.ciphertext) >> 8)
- x[5] = uint8(len(m.ciphertext))
- copy(x[6:], m.ciphertext)
+ copy(x[4:], m.ciphertext)
m.raw = x
return x
@@ -558,14 +655,14 @@ func (m *clientKeyExchangeMsg) marshal() []byte {
func (m *clientKeyExchangeMsg) unmarshal(data []byte) bool {
m.raw = data
- if len(data) < 7 {
+ if len(data) < 4 {
return false
}
- cipherTextLen := int(data[4])<<8 | int(data[5])
- if len(data) != 6+cipherTextLen {
+ l := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
+ if l != len(data)-4 {
return false
}
- m.ciphertext = data[6:]
+ m.ciphertext = data[4:]
return true
}
diff --git a/libgo/go/crypto/tls/handshake_messages_test.go b/libgo/go/crypto/tls/handshake_messages_test.go
index 64d23e0..21577dd 100644
--- a/libgo/go/crypto/tls/handshake_messages_test.go
+++ b/libgo/go/crypto/tls/handshake_messages_test.go
@@ -115,6 +115,11 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
m.serverName = randomString(rand.Intn(255), rand)
}
m.ocspStapling = rand.Intn(10) > 5
+ m.supportedPoints = randomBytes(rand.Intn(5)+1, rand)
+ m.supportedCurves = make([]uint16, rand.Intn(5)+1)
+ for i, _ := range m.supportedCurves {
+ m.supportedCurves[i] = uint16(rand.Intn(30000))
+ }
return reflect.NewValue(m)
}
diff --git a/libgo/go/crypto/tls/handshake_server.go b/libgo/go/crypto/tls/handshake_server.go
index 2255038..955811a 100644
--- a/libgo/go/crypto/tls/handshake_server.go
+++ b/libgo/go/crypto/tls/handshake_server.go
@@ -4,17 +4,7 @@
package tls
-// The handshake goroutine reads handshake messages from the record processor
-// and outputs messages to be written on another channel. It updates the record
-// processor with the state of the connection via the control channel. In the
-// case of handshake messages that need synchronous processing (because they
-// affect the handling of the next record) the record processor knows about
-// them and either waits for a control message (Finished) or includes a reply
-// channel in the message (ChangeCipherSpec).
-
import (
- "crypto/hmac"
- "crypto/rc4"
"crypto/rsa"
"crypto/subtle"
"crypto/x509"
@@ -22,16 +12,6 @@ import (
"os"
)
-type cipherSuite struct {
- id uint16 // The number of this suite on the wire.
- hashLength, cipherKeyLength int
- // TODO(agl): need a method to create the cipher and hash interfaces.
-}
-
-var cipherSuites = []cipherSuite{
- {TLS_RSA_WITH_RC4_128_SHA, 20, 16},
-}
-
func (c *Conn) serverHandshake() os.Error {
config := c.config
msg, err := c.readHandshake()
@@ -54,16 +34,38 @@ func (c *Conn) serverHandshake() os.Error {
hello := new(serverHelloMsg)
- // We only support a single ciphersuite so we look for it in the list
- // of client supported suites.
- //
- // TODO(agl): Add additional cipher suites.
- var suite *cipherSuite
+ supportedCurve := false
+Curves:
+ for _, curve := range clientHello.supportedCurves {
+ switch curve {
+ case curveP256, curveP384, curveP521:
+ supportedCurve = true
+ break Curves
+ }
+ }
+
+ supportedPointFormat := false
+ for _, pointFormat := range clientHello.supportedPoints {
+ if pointFormat == pointFormatUncompressed {
+ supportedPointFormat = true
+ break
+ }
+ }
+
+ ellipticOk := supportedCurve && supportedPointFormat
+ var suite *cipherSuite
+ var suiteId uint16
for _, id := range clientHello.cipherSuites {
- for _, supported := range cipherSuites {
- if supported.id == id {
- suite = &supported
+ for _, supported := range config.cipherSuites() {
+ if id == supported {
+ suite = cipherSuites[id]
+ // Don't select a ciphersuite which we can't
+ // support for this client.
+ if suite.elliptic && !ellipticOk {
+ continue
+ }
+ suiteId = id
break
}
}
@@ -83,14 +85,14 @@ func (c *Conn) serverHandshake() os.Error {
}
hello.vers = vers
- hello.cipherSuite = suite.id
- t := uint32(config.Time())
+ hello.cipherSuite = suiteId
+ t := uint32(config.time())
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:])
+ _, err = io.ReadFull(config.rand(), hello.random[4:])
if err != nil {
return c.sendAlert(alertInternalError)
}
@@ -112,6 +114,18 @@ func (c *Conn) serverHandshake() os.Error {
finishedHash.Write(certMsg.marshal())
c.writeRecord(recordTypeHandshake, certMsg.marshal())
+ keyAgreement := suite.ka()
+
+ skx, err := keyAgreement.generateServerKeyExchange(config, clientHello, hello)
+ if err != nil {
+ c.sendAlert(alertHandshakeFailure)
+ return err
+ }
+ if skx != nil {
+ finishedHash.Write(skx.marshal())
+ c.writeRecord(recordTypeHandshake, skx.marshal())
+ }
+
if config.AuthenticateClient {
// Request a client certificate
certReq := new(certificateRequestMsg)
@@ -208,28 +222,18 @@ func (c *Conn) serverHandshake() os.Error {
finishedHash.Write(certVerify.marshal())
}
- preMasterSecret := make([]byte, 48)
- _, err = io.ReadFull(config.Rand, preMasterSecret[2:])
+ preMasterSecret, err := keyAgreement.processClientKeyExchange(config, ckx)
if err != nil {
- return c.sendAlert(alertInternalError)
+ c.sendAlert(alertHandshakeFailure)
+ return err
}
- err = rsa.DecryptPKCS1v15SessionKey(config.Rand, config.Certificates[0].PrivateKey, ckx.ciphertext, preMasterSecret)
- if err != nil {
- return c.sendAlert(alertHandshakeFailure)
- }
- // We don't check the version number in the premaster secret. For one,
- // by checking it, we would leak information about the validity of the
- // encrypted pre-master secret. Secondly, it provides only a small
- // benefit against a downgrade attack and some implementations send the
- // wrong version anyway. See the discussion at the end of section
- // 7.4.7.1 of RFC 4346.
-
- masterSecret, clientMAC, serverMAC, clientKey, serverKey :=
- keysFromPreMasterSecret11(preMasterSecret, clientHello.random, hello.random, suite.hashLength, suite.cipherKeyLength)
-
- cipher, _ := rc4.NewCipher(clientKey)
- c.in.prepareCipherSpec(cipher, hmac.NewSHA1(clientMAC))
+ masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
+ keysFromPreMasterSecret10(preMasterSecret, clientHello.random, hello.random, suite.macLen, suite.keyLen, suite.ivLen)
+
+ clientCipher := suite.cipher(clientKey, clientIV, true /* for reading */ )
+ clientHash := suite.mac(clientMAC)
+ c.in.prepareCipherSpec(clientCipher, clientHash)
c.readRecord(recordTypeChangeCipherSpec)
if err := c.error(); err != nil {
return err
@@ -265,8 +269,9 @@ func (c *Conn) serverHandshake() os.Error {
finishedHash.Write(clientFinished.marshal())
- cipher2, _ := rc4.NewCipher(serverKey)
- c.out.prepareCipherSpec(cipher2, hmac.NewSHA1(serverMAC))
+ serverCipher := suite.cipher(serverKey, serverIV, false /* not for reading */ )
+ serverHash := suite.mac(serverMAC)
+ c.out.prepareCipherSpec(serverCipher, serverHash)
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
finished := new(finishedMsg)
@@ -274,7 +279,7 @@ func (c *Conn) serverHandshake() os.Error {
c.writeRecord(recordTypeHandshake, finished.marshal())
c.handshakeComplete = true
- c.cipherSuite = TLS_RSA_WITH_RC4_128_SHA
+ c.cipherSuite = suiteId
return nil
}
diff --git a/libgo/go/crypto/tls/handshake_server_test.go b/libgo/go/crypto/tls/handshake_server_test.go
index efdbb66..5cf3ae0 100644
--- a/libgo/go/crypto/tls/handshake_server_test.go
+++ b/libgo/go/crypto/tls/handshake_server_test.go
@@ -5,8 +5,8 @@
package tls
import (
- // "bytes"
"big"
+ "bytes"
"crypto/rsa"
"encoding/hex"
"flag"
@@ -14,7 +14,6 @@ import (
"net"
"os"
"testing"
- // "testing/script"
)
type zeroSource struct{}
@@ -36,6 +35,7 @@ func init() {
testConfig.Certificates = make([]Certificate, 1)
testConfig.Certificates[0].Certificate = [][]byte{testCertificate}
testConfig.Certificates[0].PrivateKey = testPrivateKey
+ testConfig.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA}
}
func testClientHelloFailure(t *testing.T, m handshakeMessage, expected os.Error) {
@@ -71,13 +71,13 @@ func TestRejectBadProtocolVersion(t *testing.T) {
}
func TestNoSuiteOverlap(t *testing.T) {
- clientHello := &clientHelloMsg{nil, 0x0301, nil, nil, []uint16{0xff00}, []uint8{0}, false, "", false}
+ clientHello := &clientHelloMsg{nil, 0x0301, nil, nil, []uint16{0xff00}, []uint8{0}, false, "", false, nil, nil}
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}
+ clientHello := &clientHelloMsg{nil, 0x0301, nil, nil, []uint16{TLS_RSA_WITH_RC4_128_SHA}, []uint8{0xff}, false, "", false, nil, nil}
testClientHelloFailure(t, clientHello, alertHandshakeFailure)
}
@@ -107,9 +107,9 @@ func TestClose(t *testing.T) {
}
-func TestHandshakeServer(t *testing.T) {
+func testServerScript(t *testing.T, name string, serverScript [][]byte, config *Config) {
c, s := net.Pipe()
- srv := Server(s, testConfig)
+ srv := Server(s, config)
go func() {
srv.Write([]byte("hello, world\n"))
srv.Close()
@@ -124,15 +124,23 @@ func TestHandshakeServer(t *testing.T) {
bb := make([]byte, len(b))
_, err := io.ReadFull(c, bb)
if err != nil {
- t.Fatalf("#%d: %s", i, err)
+ t.Fatalf("%s #%d: %s", name, i, err)
+ }
+ if !bytes.Equal(b, bb) {
+ t.Fatalf("%s #%d: mismatch on read: got:%x want:%x", name, i, bb, b)
}
}
+}
- if !srv.haveVers || srv.vers != 0x0302 {
- t.Errorf("server version incorrect: %v %v", srv.haveVers, srv.vers)
- }
+func TestHandshakeServerRC4(t *testing.T) {
+ testServerScript(t, "RC4", rc4ServerScript, testConfig)
+}
- // TODO: check protocol
+func TestHandshakeServerAES(t *testing.T) {
+ aesConfig := new(Config)
+ *aesConfig = *testConfig
+ aesConfig.CipherSuites = []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}
+ testServerScript(t, "AES", aesServerScript, aesConfig)
}
var serve = flag.Bool("serve", false, "run a TLS server on :10443")
@@ -152,7 +160,11 @@ func TestRunServer(t *testing.T) {
if err != nil {
break
}
- c.Write([]byte("hello, world\n"))
+ _, err = c.Write([]byte("hello, world\n"))
+ if err != nil {
+ t.Errorf("error from TLS: %s", err)
+ break
+ }
c.Close()
}
}
@@ -181,113 +193,324 @@ var testPrivateKey = &rsa.PrivateKey{
}
// Script of interaction with gnutls implementation.
-// The values for this test are obtained by building a test binary (gotest)
-// and then running 6.out -serve to start a server and then
-// gnutls-cli --insecure --debug 100 -p 10443 localhost
-// to dump a session.
-var serverScript = [][]byte{
- // Alternate write and read.
+// The values for this test are obtained by building and running in server mode:
+// % gotest -match "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
+var rc4ServerScript = [][]byte{
{
- 0x16, 0x03, 0x02, 0x00, 0x71, 0x01, 0x00, 0x00, 0x6d, 0x03, 0x02, 0x4b, 0xd4, 0xee, 0x6e, 0xab,
- 0x0b, 0xc3, 0x01, 0xd6, 0x8d, 0xe0, 0x72, 0x7e, 0x6c, 0x04, 0xbe, 0x9a, 0x3c, 0xa3, 0xd8, 0x95,
- 0x28, 0x00, 0xb2, 0xe8, 0x1f, 0xdd, 0xb0, 0xec, 0xca, 0x46, 0x1f, 0x00, 0x00, 0x28, 0x00, 0x33,
- 0x00, 0x39, 0x00, 0x16, 0x00, 0x32, 0x00, 0x38, 0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
- 0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x0a, 0x00, 0x05, 0x00, 0x04, 0x00, 0x8c,
- 0x00, 0x8d, 0x00, 0x8b, 0x00, 0x8a, 0x01, 0x00, 0x00, 0x1c, 0x00, 0x09, 0x00, 0x03, 0x02, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x0f, 0x00, 0x00, 0x0c, 0x31, 0x39, 0x32, 0x2e, 0x31, 0x36,
- 0x38, 0x2e, 0x30, 0x2e, 0x31, 0x30,
+ 0x16, 0x03, 0x02, 0x00, 0x7f, 0x01, 0x00, 0x00,
+ 0x7b, 0x03, 0x02, 0x4d, 0x08, 0x1f, 0x5a, 0x7a,
+ 0x0a, 0x92, 0x2f, 0xf0, 0x73, 0x16, 0x3a, 0x88,
+ 0x14, 0x85, 0x4c, 0x98, 0x15, 0x7b, 0x65, 0xe0,
+ 0x78, 0xd0, 0xed, 0xd0, 0xf3, 0x65, 0x20, 0xeb,
+ 0x80, 0xd1, 0x0b, 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, 0x02, 0x00, 0x2a,
- 0x02, 0x00, 0x00, 0x26, 0x03, 0x02, 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, 0x02, 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, 0x02, 0x00, 0x04,
- 0x0e, 0x00, 0x00, 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, 0x04, 0x0e,
+ 0x00, 0x00, 0x00,
},
{
- 0x16, 0x03, 0x02, 0x00, 0x86, 0x10, 0x00, 0x00, 0x82, 0x00, 0x80, 0x3b, 0x7a, 0x9b, 0x05, 0xfd,
- 0x1b, 0x0d, 0x81, 0xf0, 0xac, 0x59, 0x57, 0x4e, 0xb6, 0xf5, 0x81, 0xed, 0x52, 0x78, 0xc5, 0xff,
- 0x36, 0x33, 0x9c, 0x94, 0x31, 0xc3, 0x14, 0x98, 0x5d, 0xa0, 0x49, 0x23, 0x11, 0x67, 0xdf, 0x73,
- 0x1b, 0x81, 0x0b, 0xdd, 0x10, 0xda, 0xee, 0xb5, 0x68, 0x61, 0xa9, 0xb6, 0x15, 0xae, 0x1a, 0x11,
- 0x31, 0x42, 0x2e, 0xde, 0x01, 0x4b, 0x81, 0x70, 0x03, 0xc8, 0x5b, 0xca, 0x21, 0x88, 0x25, 0xef,
- 0x89, 0xf0, 0xb7, 0xff, 0x24, 0x32, 0xd3, 0x14, 0x76, 0xe2, 0x50, 0x5c, 0x2e, 0x75, 0x9d, 0x5c,
- 0xa9, 0x80, 0x3d, 0x6f, 0xd5, 0x46, 0xd3, 0xdb, 0x42, 0x6e, 0x55, 0x81, 0x88, 0x42, 0x0e, 0x45,
- 0xfe, 0x9e, 0xe4, 0x41, 0x79, 0xcf, 0x71, 0x0e, 0xed, 0x27, 0xa8, 0x20, 0x05, 0xe9, 0x7a, 0x42,
- 0x4f, 0x05, 0x10, 0x2e, 0x52, 0x5d, 0x8c, 0x3c, 0x40, 0x49, 0x4c,
-
- 0x14, 0x03, 0x02, 0x00, 0x01, 0x01,
-
- 0x16, 0x03, 0x02, 0x00, 0x24, 0x8b, 0x12, 0x24, 0x06, 0xaa, 0x92, 0x74, 0xa1, 0x46, 0x6f, 0xc1,
- 0x4e, 0x4a, 0xf7, 0x16, 0xdd, 0xd6, 0xe1, 0x2d, 0x37, 0x0b, 0x44, 0xba, 0xeb, 0xc4, 0x6c, 0xc7,
- 0xa0, 0xb7, 0x8c, 0x9d, 0x24, 0xbd, 0x99, 0x33, 0x1e,
+ 0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
+ 0x82, 0x00, 0x80, 0x3c, 0x13, 0xd7, 0x12, 0xc1,
+ 0x6a, 0xf0, 0x3f, 0x8c, 0xa1, 0x35, 0x5d, 0xc5,
+ 0x89, 0x1e, 0x9e, 0xcd, 0x32, 0xc7, 0x9e, 0xe6,
+ 0xae, 0xd5, 0xf1, 0xbf, 0x70, 0xd7, 0xa9, 0xef,
+ 0x2c, 0x4c, 0xf4, 0x22, 0xbc, 0x17, 0x17, 0xaa,
+ 0x05, 0xf3, 0x9f, 0x80, 0xf2, 0xe9, 0x82, 0x2f,
+ 0x2a, 0x15, 0x54, 0x0d, 0x16, 0x0e, 0x77, 0x4c,
+ 0x28, 0x3c, 0x03, 0x2d, 0x2d, 0xd7, 0xc8, 0x64,
+ 0xd9, 0x59, 0x4b, 0x1c, 0xf4, 0xde, 0xff, 0x2f,
+ 0xbc, 0x94, 0xaf, 0x18, 0x26, 0x37, 0xce, 0x4f,
+ 0x84, 0x74, 0x2e, 0x45, 0x66, 0x7c, 0x0c, 0x54,
+ 0x46, 0x36, 0x5f, 0x65, 0x21, 0x7b, 0x83, 0x8c,
+ 0x6d, 0x76, 0xcd, 0x0d, 0x9f, 0xda, 0x1c, 0xa4,
+ 0x6e, 0xfe, 0xb1, 0xf7, 0x09, 0x0d, 0xfb, 0x74,
+ 0x66, 0x34, 0x99, 0x89, 0x7f, 0x5f, 0x77, 0x87,
+ 0x4a, 0x66, 0x4b, 0xa9, 0x59, 0x57, 0xe3, 0x56,
+ 0x0d, 0xdd, 0xd8, 0x14, 0x03, 0x01, 0x00, 0x01,
+ 0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xc0, 0x4e,
+ 0xd3, 0x0f, 0xb5, 0xc0, 0x57, 0xa6, 0x18, 0x80,
+ 0x80, 0x6b, 0x49, 0xfe, 0xbd, 0x3a, 0x7a, 0x2c,
+ 0xef, 0x70, 0xb5, 0x1c, 0xd2, 0xdf, 0x5f, 0x78,
+ 0x5a, 0xd8, 0x4f, 0xa0, 0x95, 0xb4, 0xb3, 0xb5,
+ 0xaa, 0x3b,
},
{
- 0x14, 0x03, 0x02, 0x00, 0x01,
- 0x01,
+ 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+ 0x01, 0x00, 0x24, 0x9d, 0xc9, 0xda, 0xdf, 0xeb,
+ 0xc8, 0xdb, 0xf8, 0x94, 0xa5, 0xef, 0xd5, 0xfc,
+ 0x89, 0x01, 0x64, 0x30, 0x77, 0x5a, 0x18, 0x4b,
+ 0x16, 0x79, 0x9c, 0xf6, 0xf5, 0x09, 0x22, 0x12,
+ 0x4c, 0x3e, 0xa8, 0x8e, 0x91, 0xa5, 0x24,
+ },
+}
- 0x16, 0x03, 0x02, 0x00, 0x24,
- 0x6e, 0xd1, 0x3e, 0x49, 0x68, 0xc1, 0xa0, 0xa5, 0xb7, 0xaf, 0xb0, 0x7c, 0x52, 0x1f, 0xf7, 0x2d,
- 0x51, 0xf3, 0xa5, 0xb6, 0xf6, 0xd4, 0x18, 0x4b, 0x7a, 0xd5, 0x24, 0x1d, 0x09, 0xb6, 0x41, 0x1c,
- 0x1c, 0x98, 0xf6, 0x90,
+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,
+ },
- 0x17, 0x03, 0x02, 0x00, 0x21,
- 0x50, 0xb7, 0x92, 0x4f, 0xd8, 0x78, 0x29, 0xa2, 0xe7, 0xa5, 0xa6, 0xbd, 0x1a, 0x0c, 0xf1, 0x5a,
- 0x6e, 0x6c, 0xeb, 0x38, 0x99, 0x9b, 0x3c, 0xfd, 0xee, 0x53, 0xe8, 0x4d, 0x7b, 0xa5, 0x5b, 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, 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,
+ 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,
+ },
- 0xb9,
+ {
+ 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,
+ },
- 0x15, 0x03, 0x02, 0x00, 0x16,
- 0xc7, 0xc9, 0x5a, 0x72, 0xfb, 0x02, 0xa5, 0x93, 0xdd, 0x69, 0xeb, 0x30, 0x68, 0x5e, 0xbc, 0xe0,
- 0x44, 0xb9, 0x59, 0x33, 0x68, 0xa9,
+ {
+ 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,
},
}
diff --git a/libgo/go/crypto/tls/key_agreement.go b/libgo/go/crypto/tls/key_agreement.go
new file mode 100644
index 0000000..861c64f
--- /dev/null
+++ b/libgo/go/crypto/tls/key_agreement.go
@@ -0,0 +1,246 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tls
+
+import (
+ "big"
+ "crypto/elliptic"
+ "crypto/md5"
+ "crypto/rsa"
+ "crypto/sha1"
+ "crypto/x509"
+ "io"
+ "os"
+)
+
+// rsaKeyAgreement implements the standard TLS key agreement where the client
+// encrypts the pre-master secret to the server's public key.
+type rsaKeyAgreement struct{}
+
+func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, os.Error) {
+ return nil, nil
+}
+
+func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKeyExchangeMsg) ([]byte, os.Error) {
+ preMasterSecret := make([]byte, 48)
+ _, err := io.ReadFull(config.rand(), preMasterSecret[2:])
+ if err != nil {
+ return nil, err
+ }
+
+ if len(ckx.ciphertext) < 2 {
+ return nil, os.ErrorString("bad ClientKeyExchange")
+ }
+ ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])
+ if ciphertextLen != len(ckx.ciphertext)-2 {
+ return nil, os.ErrorString("bad ClientKeyExchange")
+ }
+ ciphertext := ckx.ciphertext[2:]
+
+ err = rsa.DecryptPKCS1v15SessionKey(config.rand(), config.Certificates[0].PrivateKey, ciphertext, preMasterSecret)
+ if err != nil {
+ return nil, err
+ }
+ // We don't check the version number in the premaster secret. For one,
+ // by checking it, we would leak information about the validity of the
+ // encrypted pre-master secret. Secondly, it provides only a small
+ // benefit against a downgrade attack and some implementations send the
+ // wrong version anyway. See the discussion at the end of section
+ // 7.4.7.1 of RFC 4346.
+ return preMasterSecret, nil
+}
+
+func (ka rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) os.Error {
+ return os.ErrorString("unexpected ServerKeyExchange")
+}
+
+func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, os.Error) {
+ preMasterSecret := make([]byte, 48)
+ preMasterSecret[0] = byte(clientHello.vers >> 8)
+ preMasterSecret[1] = byte(clientHello.vers)
+ _, err := io.ReadFull(config.rand(), preMasterSecret[2:])
+ if err != nil {
+ return nil, nil, err
+ }
+
+ encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret)
+ if err != nil {
+ return nil, nil, err
+ }
+ ckx := new(clientKeyExchangeMsg)
+ ckx.ciphertext = make([]byte, len(encrypted)+2)
+ ckx.ciphertext[0] = byte(len(encrypted) >> 8)
+ ckx.ciphertext[1] = byte(len(encrypted))
+ copy(ckx.ciphertext[2:], encrypted)
+ return preMasterSecret, ckx, nil
+}
+
+
+// md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the
+// concatenation of an MD5 and SHA1 hash.
+func md5SHA1Hash(slices ...[]byte) []byte {
+ md5sha1 := make([]byte, md5.Size+sha1.Size)
+ hmd5 := md5.New()
+ for _, slice := range slices {
+ hmd5.Write(slice)
+ }
+ copy(md5sha1, hmd5.Sum())
+
+ hsha1 := sha1.New()
+ for _, slice := range slices {
+ hsha1.Write(slice)
+ }
+ copy(md5sha1[md5.Size:], hsha1.Sum())
+ return md5sha1
+}
+
+// ecdheRSAKeyAgreement implements a TLS key agreement where the server
+// generates a ephemeral EC public/private key pair and signs it. The
+// pre-master secret is then calculated using ECDH.
+type ecdheRSAKeyAgreement struct {
+ privateKey []byte
+ curve *elliptic.Curve
+ x, y *big.Int
+}
+
+func (ka *ecdheRSAKeyAgreement) generateServerKeyExchange(config *Config, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, os.Error) {
+ var curveid uint16
+
+Curve:
+ for _, c := range clientHello.supportedCurves {
+ switch c {
+ case curveP256:
+ ka.curve = elliptic.P256()
+ curveid = c
+ break Curve
+ case curveP384:
+ ka.curve = elliptic.P384()
+ curveid = c
+ break Curve
+ case curveP521:
+ ka.curve = elliptic.P521()
+ curveid = c
+ break Curve
+ }
+ }
+
+ var x, y *big.Int
+ var err os.Error
+ ka.privateKey, x, y, err = ka.curve.GenerateKey(config.rand())
+ if err != nil {
+ return nil, err
+ }
+ ecdhePublic := ka.curve.Marshal(x, y)
+
+ // http://tools.ietf.org/html/rfc4492#section-5.4
+ serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic))
+ serverECDHParams[0] = 3 // named curve
+ serverECDHParams[1] = byte(curveid >> 8)
+ serverECDHParams[2] = byte(curveid)
+ serverECDHParams[3] = byte(len(ecdhePublic))
+ copy(serverECDHParams[4:], ecdhePublic)
+
+ md5sha1 := md5SHA1Hash(clientHello.random, hello.random, serverECDHParams)
+ sig, err := rsa.SignPKCS1v15(config.rand(), config.Certificates[0].PrivateKey, rsa.HashMD5SHA1, md5sha1)
+ if err != nil {
+ return nil, os.ErrorString("failed to sign ECDHE parameters: " + err.String())
+ }
+
+ skx := new(serverKeyExchangeMsg)
+ skx.key = make([]byte, len(serverECDHParams)+2+len(sig))
+ copy(skx.key, serverECDHParams)
+ k := skx.key[len(serverECDHParams):]
+ k[0] = byte(len(sig) >> 8)
+ k[1] = byte(len(sig))
+ copy(k[2:], sig)
+
+ return skx, nil
+}
+
+func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKeyExchangeMsg) ([]byte, os.Error) {
+ if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
+ return nil, os.ErrorString("bad ClientKeyExchange")
+ }
+ x, y := ka.curve.Unmarshal(ckx.ciphertext[1:])
+ if x == nil {
+ return nil, os.ErrorString("bad ClientKeyExchange")
+ }
+ x, _ = ka.curve.ScalarMult(x, y, ka.privateKey)
+ preMasterSecret := make([]byte, (ka.curve.BitSize+7)>>3)
+ xBytes := x.Bytes()
+ copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
+
+ return preMasterSecret, nil
+}
+
+func (ka *ecdheRSAKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) os.Error {
+ if len(skx.key) < 4 {
+ goto Error
+ }
+ if skx.key[0] != 3 { // named curve
+ return os.ErrorString("server selected unsupported curve")
+ }
+ curveid := uint16(skx.key[1])<<8 | uint16(skx.key[2])
+
+ switch curveid {
+ case curveP256:
+ ka.curve = elliptic.P256()
+ case curveP384:
+ ka.curve = elliptic.P384()
+ case curveP521:
+ ka.curve = elliptic.P521()
+ default:
+ return os.ErrorString("server selected unsupported curve")
+ }
+
+ publicLen := int(skx.key[3])
+ if publicLen+4 > len(skx.key) {
+ goto Error
+ }
+ ka.x, ka.y = ka.curve.Unmarshal(skx.key[4 : 4+publicLen])
+ if ka.x == nil {
+ goto Error
+ }
+ serverECDHParams := skx.key[:4+publicLen]
+
+ sig := skx.key[4+publicLen:]
+ if len(sig) < 2 {
+ goto Error
+ }
+ sigLen := int(sig[0])<<8 | int(sig[1])
+ if sigLen+2 != len(sig) {
+ goto Error
+ }
+ sig = sig[2:]
+
+ md5sha1 := md5SHA1Hash(clientHello.random, serverHello.random, serverECDHParams)
+ return rsa.VerifyPKCS1v15(cert.PublicKey.(*rsa.PublicKey), rsa.HashMD5SHA1, md5sha1, sig)
+
+Error:
+ return os.ErrorString("invalid ServerKeyExchange")
+}
+
+func (ka *ecdheRSAKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, os.Error) {
+ if ka.curve == nil {
+ return nil, nil, os.ErrorString("missing ServerKeyExchange message")
+ }
+ priv, mx, my, err := ka.curve.GenerateKey(config.rand())
+ if err != nil {
+ return nil, nil, err
+ }
+ x, _ := ka.curve.ScalarMult(ka.x, ka.y, priv)
+ preMasterSecret := make([]byte, (ka.curve.BitSize+7)>>3)
+ xBytes := x.Bytes()
+ copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
+
+ serialised := ka.curve.Marshal(mx, my)
+
+ ckx := new(clientKeyExchangeMsg)
+ ckx.ciphertext = make([]byte, 1+len(serialised))
+ ckx.ciphertext[0] = byte(len(serialised))
+ copy(ckx.ciphertext[1:], serialised)
+
+ return preMasterSecret, ckx, nil
+}
diff --git a/libgo/go/crypto/tls/prf.go b/libgo/go/crypto/tls/prf.go
index b206d26..478cf65 100644
--- a/libgo/go/crypto/tls/prf.go
+++ b/libgo/go/crypto/tls/prf.go
@@ -44,8 +44,8 @@ func pHash(result, secret, seed []byte, hash func() hash.Hash) {
}
}
-// pRF11 implements the TLS 1.1 pseudo-random function, as defined in RFC 4346, section 5.
-func pRF11(result, secret, label, seed []byte) {
+// pRF10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, section 5.
+func pRF10(result, secret, label, seed []byte) {
hashSHA1 := sha1.New
hashMD5 := md5.New
@@ -75,25 +75,32 @@ 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 and cipher keys, as defined in RFC
-// 4346, section 6.3.
-func keysFromPreMasterSecret11(preMasterSecret, clientRandom, serverRandom []byte, macLen, keyLen int) (masterSecret, clientMAC, serverMAC, clientKey, serverKey []byte) {
+// secret, given the lengths of the MAC key, cipher key and IV, as defined in
+// RFC 2246, section 6.3.
+func keysFromPreMasterSecret10(preMasterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
var seed [tlsRandomLength * 2]byte
copy(seed[0:len(clientRandom)], clientRandom)
copy(seed[len(clientRandom):], serverRandom)
masterSecret = make([]byte, masterSecretLength)
- pRF11(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
+ pRF10(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
copy(seed[0:len(clientRandom)], serverRandom)
copy(seed[len(serverRandom):], clientRandom)
- n := 2*macLen + 2*keyLen
+ n := 2*macLen + 2*keyLen + 2*ivLen
keyMaterial := make([]byte, n)
- pRF11(keyMaterial, masterSecret, keyExpansionLabel, seed[0:])
- clientMAC = keyMaterial[0:macLen]
- serverMAC = keyMaterial[macLen : macLen*2]
- clientKey = keyMaterial[macLen*2 : macLen*2+keyLen]
- serverKey = keyMaterial[macLen*2+keyLen:]
+ pRF10(keyMaterial, masterSecret, keyExpansionLabel, seed[0:])
+ clientMAC = keyMaterial[:macLen]
+ keyMaterial = keyMaterial[macLen:]
+ serverMAC = keyMaterial[:macLen]
+ keyMaterial = keyMaterial[macLen:]
+ clientKey = keyMaterial[:keyLen]
+ keyMaterial = keyMaterial[keyLen:]
+ serverKey = keyMaterial[:keyLen]
+ keyMaterial = keyMaterial[keyLen:]
+ clientIV = keyMaterial[:ivLen]
+ keyMaterial = keyMaterial[ivLen:]
+ serverIV = keyMaterial[:ivLen]
return
}
@@ -125,7 +132,7 @@ func finishedSum(md5, sha1, label, masterSecret []byte) []byte {
copy(seed, md5)
copy(seed[len(md5):], sha1)
out := make([]byte, finishedVerifyLength)
- pRF11(out, masterSecret, label, seed)
+ pRF10(out, masterSecret, label, seed)
return out
}
diff --git a/libgo/go/crypto/tls/prf_test.go b/libgo/go/crypto/tls/prf_test.go
index d99bab5..f8c4acb 100644
--- a/libgo/go/crypto/tls/prf_test.go
+++ b/libgo/go/crypto/tls/prf_test.go
@@ -47,7 +47,7 @@ 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 := keysFromPreMasterSecret11(in, clientRandom, serverRandom, test.macLen, test.keyLen)
+ master, clientMAC, serverMAC, clientKey, serverKey, _, _ := keysFromPreMasterSecret10(in, clientRandom, serverRandom, test.macLen, test.keyLen, 0)
masterString := hex.EncodeToString(master)
clientMACString := hex.EncodeToString(clientMAC)
serverMACString := hex.EncodeToString(serverMAC)
diff --git a/libgo/go/crypto/tls/tls.go b/libgo/go/crypto/tls/tls.go
index 61f0a97..b11d322 100644
--- a/libgo/go/crypto/tls/tls.go
+++ b/libgo/go/crypto/tls/tls.go
@@ -15,19 +15,31 @@ import (
"strings"
)
+// Server returns a new TLS server side connection
+// using conn as the underlying transport.
+// The configuration config must be non-nil and must have
+// at least one certificate.
func Server(conn net.Conn, config *Config) *Conn {
return &Conn{conn: conn, config: config}
}
+// Client returns a new TLS client side connection
+// using conn as the underlying transport.
+// Client interprets a nil configuration as equivalent to
+// the zero configuration; see the documentation of Config
+// for the defaults.
func Client(conn net.Conn, config *Config) *Conn {
return &Conn{conn: conn, config: config, isClient: true}
}
+// A Listener implements a network listener (net.Listener) for TLS connections.
type Listener struct {
listener net.Listener
config *Config
}
+// Accept waits for and returns the next incoming TLS connection.
+// The returned connection c is a *tls.Conn.
func (l *Listener) Accept() (c net.Conn, err os.Error) {
c, err = l.listener.Accept()
if err != nil {
@@ -37,8 +49,10 @@ func (l *Listener) Accept() (c net.Conn, err os.Error) {
return
}
+// Close closes the listener.
func (l *Listener) Close() os.Error { return l.listener.Close() }
+// Addr returns the listener's network address.
func (l *Listener) Addr() net.Addr { return l.listener.Addr() }
// NewListener creates a Listener which accepts connections from an inner
@@ -52,7 +66,11 @@ func NewListener(listener net.Listener, config *Config) (l *Listener) {
return
}
-func Listen(network, laddr string, config *Config) (net.Listener, os.Error) {
+// Listen creates a TLS listener accepting connections on the
+// given network address using net.Listen.
+// The configuration config must be non-nil and must have
+// at least one certificate.
+func Listen(network, laddr string, config *Config) (*Listener, os.Error) {
if config == nil || len(config.Certificates) == 0 {
return nil, os.NewError("tls.Listen: no certificates in configuration")
}
@@ -63,7 +81,13 @@ func Listen(network, laddr string, config *Config) (net.Listener, os.Error) {
return NewListener(l, config), nil
}
-func Dial(network, laddr, raddr string) (net.Conn, os.Error) {
+// Dial connects to the given network address using net.Dial
+// and then initiates a TLS handshake, returning the resulting
+// TLS connection.
+// Dial interprets a nil configuration as equivalent to
+// the zero configuration; see the documentation of Config
+// for the defaults.
+func Dial(network, laddr, raddr string, config *Config) (*Conn, os.Error) {
c, err := net.Dial(network, laddr, raddr)
if err != nil {
return nil, err
@@ -75,15 +99,21 @@ func Dial(network, laddr, raddr string) (net.Conn, os.Error) {
}
hostname := raddr[:colonPos]
- config := defaultConfig()
- config.ServerName = hostname
+ if config == nil {
+ config = defaultConfig()
+ }
+ if config.ServerName != "" {
+ // Make a copy to avoid polluting argument or default.
+ c := *config
+ c.ServerName = hostname
+ config = &c
+ }
conn := Client(c, config)
- err = conn.Handshake()
- if err == nil {
- return conn, nil
+ if err = conn.Handshake(); err != nil {
+ c.Close()
+ return nil, err
}
- c.Close()
- return nil, err
+ return conn, nil
}
// LoadX509KeyPair reads and parses a public/private key pair from a pair of
diff --git a/libgo/go/crypto/twofish/twofish.go b/libgo/go/crypto/twofish/twofish.go
new file mode 100644
index 0000000..62253e7
--- /dev/null
+++ b/libgo/go/crypto/twofish/twofish.go
@@ -0,0 +1,358 @@
+// 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.
+
+// This package implements Bruce Schneier's Twofish encryption algorithm.
+package twofish
+
+// Twofish is defined in http://www.schneier.com/paper-twofish-paper.pdf [TWOFISH]
+
+// This code is a port of the LibTom C implementation.
+// See http://libtom.org/?page=features&newsitems=5&whatfile=crypt.
+// LibTomCrypt is free for all purposes under the public domain.
+// It was heavily inspired by the go blowfish package.
+
+import (
+ "os"
+ "strconv"
+)
+
+// BlockSize is the constant block size of Twofish.
+const BlockSize = 16
+
+const mdsPolynomial = 0x169 // x^8 + x^6 + x^5 + x^3 + 1, see [TWOFISH] 4.2
+const rsPolynomial = 0x14d // x^8 + x^6 + x^3 + x^2 + 1, see [TWOFISH] 4.3
+
+// A Cipher is an instance of Twofish encryption using a particular key.
+type Cipher struct {
+ s [4][256]uint32
+ k [40]uint32
+}
+
+type KeySizeError int
+
+func (k KeySizeError) String() string {
+ return "crypto/twofish: invalid key size " + strconv.Itoa(int(k))
+}
+
+// NewCipher creates and returns a Cipher.
+// The key argument should be the Twofish key, 16, 24 or 32 bytes.
+func NewCipher(key []byte) (*Cipher, os.Error) {
+ keylen := len(key)
+
+ if keylen != 16 && keylen != 24 && keylen != 32 {
+ return nil, KeySizeError(keylen)
+ }
+
+ // k is the number of 64 bit words in key
+ k := keylen / 8
+
+ // Create the S[..] words
+ var S [4 * 4]byte
+ for i := 0; i < k; i++ {
+ // Computes [y0 y1 y2 y3] = rs . [x0 x1 x2 x3 x4 x5 x6 x7]
+ for j, rsRow := range rs {
+ for k, rsVal := range rsRow {
+ S[4*i+j] ^= gfMult(key[8*i+k], rsVal, rsPolynomial)
+ }
+ }
+ }
+
+ // Calculate subkeys
+ c := new(Cipher)
+ var tmp [4]byte
+ for i := byte(0); i < 20; i++ {
+ // A = h(p * 2x, Me)
+ for j := range tmp {
+ tmp[j] = 2 * i
+ }
+ A := h(tmp[:], key, 0)
+
+ // B = rolc(h(p * (2x + 1), Mo), 8)
+ for j := range tmp {
+ tmp[j] = 2*i + 1
+ }
+ B := h(tmp[:], key, 1)
+ B = rol(B, 8)
+
+ c.k[2*i] = A + B
+
+ // K[2i+1] = (A + 2B) <<< 9
+ c.k[2*i+1] = rol(2*B+A, 9)
+ }
+
+ // Calculate sboxes
+ switch k {
+ case 2:
+ for i := range c.s[0] {
+ c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][byte(i)]^S[0]]^S[4]], 0)
+ c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][byte(i)]^S[1]]^S[5]], 1)
+ c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][byte(i)]^S[2]]^S[6]], 2)
+ c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][byte(i)]^S[3]]^S[7]], 3)
+ }
+ case 3:
+ for i := range c.s[0] {
+ c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]], 0)
+ c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[1]]^S[5]]^S[9]], 1)
+ c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]], 2)
+ c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[3]]^S[7]]^S[11]], 3)
+ }
+ default:
+ for i := range c.s[0] {
+ c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]]^S[12]], 0)
+ c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[1]]^S[5]]^S[9]]^S[13]], 1)
+ c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]]^S[14]], 2)
+ c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][sbox[1][byte(i)]^S[3]]^S[7]]^S[11]]^S[15]], 3)
+ }
+ }
+
+ return c, nil
+}
+
+// Reset zeros the key data, so that it will no longer appear in the process's
+// memory.
+func (c *Cipher) Reset() {
+ for i := range c.k {
+ c.k[i] = 0
+ }
+ for i := range c.s {
+ for j := 0; j < 265; j++ {
+ c.s[i][j] = 0
+ }
+ }
+}
+
+// BlockSize returns the Twofish block size, 16 bytes.
+func (c *Cipher) BlockSize() int { return BlockSize }
+
+// store32l stores src in dst in little-endian form.
+func store32l(dst []byte, src uint32) {
+ dst[0] = byte(src)
+ dst[1] = byte(src >> 8)
+ dst[2] = byte(src >> 16)
+ dst[3] = byte(src >> 24)
+ return
+}
+
+// load32l reads a little-endian uint32 from src.
+func load32l(src []byte) uint32 {
+ return uint32(src[0]) | uint32(src[1])<<8 | uint32(src[2])<<16 | uint32(src[3])<<24
+}
+
+// rol returns x after a left circular rotation of y bits.
+func rol(x, y uint32) uint32 {
+ return (x << (y & 31)) | (x >> (32 - (y & 31)))
+}
+
+// ror returns x after a right circular rotation of y bits.
+func ror(x, y uint32) uint32 {
+ return (x >> (y & 31)) | (x << (32 - (y & 31)))
+}
+
+// The RS matrix. See [TWOFISH] 4.3
+var rs = [4][8]byte{
+ {0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E},
+ {0xA4, 0x56, 0x82, 0xF3, 0x1E, 0xC6, 0x68, 0xE5},
+ {0x02, 0xA1, 0xFC, 0xC1, 0x47, 0xAE, 0x3D, 0x19},
+ {0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E, 0x03},
+}
+
+// sbox tables
+var sbox = [2][256]byte{
+ {
+ 0xa9, 0x67, 0xb3, 0xe8, 0x04, 0xfd, 0xa3, 0x76, 0x9a, 0x92, 0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38,
+ 0x0d, 0xc6, 0x35, 0x98, 0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13, 0x94, 0x48,
+ 0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23, 0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82,
+ 0x63, 0x01, 0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe, 0x16, 0x0c, 0xe3, 0x61,
+ 0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c, 0x25, 0x0b, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1,
+ 0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95, 0x03, 0x56, 0xd4, 0x1c, 0x1e, 0xd7,
+ 0xfb, 0xc3, 0x8e, 0xb5, 0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9, 0x62, 0x71,
+ 0x81, 0x79, 0x09, 0xad, 0x24, 0xcd, 0xf9, 0xd8, 0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x08, 0x86, 0xe7,
+ 0xa1, 0x1d, 0xaa, 0xed, 0x06, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11, 0x31, 0xc2, 0x27, 0x90,
+ 0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c, 0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0x0a, 0xef,
+ 0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87, 0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64,
+ 0x2a, 0xce, 0xcb, 0x2f, 0xfc, 0x97, 0x05, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0x0e, 0xa7, 0x5a,
+ 0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x02, 0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d,
+ 0x57, 0xc7, 0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34,
+ 0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc, 0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4,
+ 0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0x0f, 0x00, 0x6f, 0x9d, 0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0,
+ },
+ {
+ 0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3, 0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b,
+ 0xd6, 0x32, 0xd8, 0xfd, 0x37, 0x71, 0xf1, 0xe1, 0x30, 0x0f, 0xf8, 0x1b, 0x87, 0xfa, 0x06, 0x3f,
+ 0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x00, 0xbc, 0x9d, 0x6d, 0xc1, 0xb1, 0x0e, 0x80, 0x5d, 0xd2, 0xd5,
+ 0xa0, 0x84, 0x07, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54, 0x92, 0x74, 0x36, 0x51,
+ 0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60, 0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c,
+ 0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3, 0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8,
+ 0xa6, 0x83, 0x20, 0xff, 0x9f, 0x77, 0xc3, 0xcc, 0x03, 0x6f, 0x08, 0xbf, 0x40, 0xe7, 0x2b, 0xe2,
+ 0x79, 0x0c, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9, 0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17,
+ 0x66, 0x94, 0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0x0b, 0x72, 0xa7, 0x1c, 0xef, 0xd1, 0x53, 0x3e,
+ 0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76, 0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9,
+ 0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x01, 0x18, 0x23, 0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48,
+ 0x4f, 0xf2, 0x65, 0x8e, 0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f, 0x05, 0x64,
+ 0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5, 0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69,
+ 0x29, 0x2e, 0xac, 0x15, 0x59, 0xa8, 0x0a, 0x9e, 0x6e, 0x47, 0xdf, 0x34, 0x35, 0x6a, 0xcf, 0xdc,
+ 0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4, 0xed, 0xab, 0x12, 0xa2, 0x0d, 0x52, 0xbb, 0x02, 0x2f, 0xa9,
+ 0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x04, 0xf6, 0xc2, 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xbe, 0x91,
+ },
+}
+
+// gfMult returns a·b in GF(2^8)/p
+func gfMult(a, b byte, p uint32) byte {
+ B := [2]uint32{0, uint32(b)}
+ P := [2]uint32{0, p}
+ var result uint32
+
+ // branchless GF multiplier
+ for i := 0; i < 7; i++ {
+ result ^= B[a&1]
+ a >>= 1
+ B[1] = P[B[1]>>7] ^ (B[1] << 1)
+ }
+ result ^= B[a&1]
+ return byte(result)
+}
+
+// mdsColumnMult calculates y{col} where [y0 y1 y2 y3] = MDS · [x0]
+func mdsColumnMult(in byte, col int) uint32 {
+ mul01 := in
+ mul5B := gfMult(in, 0x5B, mdsPolynomial)
+ mulEF := gfMult(in, 0xEF, mdsPolynomial)
+
+ switch col {
+ case 0:
+ return uint32(mul01) | uint32(mul5B)<<8 | uint32(mulEF)<<16 | uint32(mulEF)<<24
+ case 1:
+ return uint32(mulEF) | uint32(mulEF)<<8 | uint32(mul5B)<<16 | uint32(mul01)<<24
+ case 2:
+ return uint32(mul5B) | uint32(mulEF)<<8 | uint32(mul01)<<16 | uint32(mulEF)<<24
+ case 3:
+ return uint32(mul5B) | uint32(mul01)<<8 | uint32(mulEF)<<16 | uint32(mul5B)<<24
+ }
+
+ panic("unreachable")
+}
+
+// h implements the S-box generation function. See [TWOFISH] 4.3.5
+func h(in, key []byte, offset int) uint32 {
+ var y [4]byte
+ for x := range y {
+ y[x] = in[x]
+ }
+ switch len(key) / 8 {
+ case 4:
+ y[0] = sbox[1][y[0]] ^ key[4*(6+offset)+0]
+ y[1] = sbox[0][y[1]] ^ key[4*(6+offset)+1]
+ y[2] = sbox[0][y[2]] ^ key[4*(6+offset)+2]
+ y[3] = sbox[1][y[3]] ^ key[4*(6+offset)+3]
+ fallthrough
+ case 3:
+ y[0] = sbox[1][y[0]] ^ key[4*(4+offset)+0]
+ y[1] = sbox[1][y[1]] ^ key[4*(4+offset)+1]
+ y[2] = sbox[0][y[2]] ^ key[4*(4+offset)+2]
+ y[3] = sbox[0][y[3]] ^ key[4*(4+offset)+3]
+ fallthrough
+ case 2:
+ y[0] = sbox[1][sbox[0][sbox[0][y[0]]^key[4*(2+offset)+0]]^key[4*(0+offset)+0]]
+ y[1] = sbox[0][sbox[0][sbox[1][y[1]]^key[4*(2+offset)+1]]^key[4*(0+offset)+1]]
+ y[2] = sbox[1][sbox[1][sbox[0][y[2]]^key[4*(2+offset)+2]]^key[4*(0+offset)+2]]
+ y[3] = sbox[0][sbox[1][sbox[1][y[3]]^key[4*(2+offset)+3]]^key[4*(0+offset)+3]]
+ }
+ // [y0 y1 y2 y3] = MDS . [x0 x1 x2 x3]
+ var mdsMult uint32
+ for i := range y {
+ mdsMult ^= mdsColumnMult(y[i], i)
+ }
+ return mdsMult
+}
+
+// Encrypt encrypts a 16-byte block from src to dst, which may overlap.
+// Note that for amounts of data larger than a block,
+// it is not safe to just call Encrypt on successive blocks;
+// instead, use an encryption mode like CBC (see crypto/block/cbc.go).
+func (c *Cipher) Encrypt(dst, src []byte) {
+ S1 := c.s[0]
+ S2 := c.s[1]
+ S3 := c.s[2]
+ S4 := c.s[3]
+
+ // Load input
+ ia := load32l(src[0:4])
+ ib := load32l(src[4:8])
+ ic := load32l(src[8:12])
+ id := load32l(src[12:16])
+
+ // Pre-whitening
+ ia ^= c.k[0]
+ ib ^= c.k[1]
+ ic ^= c.k[2]
+ id ^= c.k[3]
+
+ for i := 0; i < 8; i++ {
+ k := c.k[8+i*4 : 12+i*4]
+ t2 := S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)]
+ t1 := S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2
+ ic = ror(ic^(t1+k[0]), 1)
+ id = rol(id, 1) ^ (t2 + t1 + k[1])
+
+ t2 = S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)]
+ t1 = S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2
+ ia = ror(ia^(t1+k[2]), 1)
+ ib = rol(ib, 1) ^ (t2 + t1 + k[3])
+ }
+
+ // Output with "undo last swap"
+ ta := ic ^ c.k[4]
+ tb := id ^ c.k[5]
+ tc := ia ^ c.k[6]
+ td := ib ^ c.k[7]
+
+ store32l(dst[0:4], ta)
+ store32l(dst[4:8], tb)
+ store32l(dst[8:12], tc)
+ store32l(dst[12:16], td)
+}
+
+// Decrypt decrypts a 16-byte block from src to dst, which may overlap.
+func (c *Cipher) Decrypt(dst, src []byte) {
+ S1 := c.s[0]
+ S2 := c.s[1]
+ S3 := c.s[2]
+ S4 := c.s[3]
+
+ // Load input
+ ta := load32l(src[0:4])
+ tb := load32l(src[4:8])
+ tc := load32l(src[8:12])
+ td := load32l(src[12:16])
+
+ // Undo undo final swap
+ ia := tc ^ c.k[6]
+ ib := td ^ c.k[7]
+ ic := ta ^ c.k[4]
+ id := tb ^ c.k[5]
+
+ for i := 8; i > 0; i-- {
+ k := c.k[4+i*4 : 8+i*4]
+ t2 := S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)]
+ t1 := S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2
+ ia = rol(ia, 1) ^ (t1 + k[2])
+ ib = ror(ib^(t2+t1+k[3]), 1)
+
+ t2 = S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)]
+ t1 = S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2
+ ic = rol(ic, 1) ^ (t1 + k[0])
+ id = ror(id^(t2+t1+k[1]), 1)
+ }
+
+ // Undo pre-whitening
+ ia ^= c.k[0]
+ ib ^= c.k[1]
+ ic ^= c.k[2]
+ id ^= c.k[3]
+
+ store32l(dst[0:4], ia)
+ store32l(dst[4:8], ib)
+ store32l(dst[8:12], ic)
+ store32l(dst[12:16], id)
+}
diff --git a/libgo/go/crypto/twofish/twofish_test.go b/libgo/go/crypto/twofish/twofish_test.go
new file mode 100644
index 0000000..303081f
--- /dev/null
+++ b/libgo/go/crypto/twofish/twofish_test.go
@@ -0,0 +1,129 @@
+// 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 twofish
+
+import (
+ "bytes"
+ "testing"
+)
+
+var qbox = [2][4][16]byte{
+ {
+ {0x8, 0x1, 0x7, 0xD, 0x6, 0xF, 0x3, 0x2, 0x0, 0xB, 0x5, 0x9, 0xE, 0xC, 0xA, 0x4},
+ {0xE, 0xC, 0xB, 0x8, 0x1, 0x2, 0x3, 0x5, 0xF, 0x4, 0xA, 0x6, 0x7, 0x0, 0x9, 0xD},
+ {0xB, 0xA, 0x5, 0xE, 0x6, 0xD, 0x9, 0x0, 0xC, 0x8, 0xF, 0x3, 0x2, 0x4, 0x7, 0x1},
+ {0xD, 0x7, 0xF, 0x4, 0x1, 0x2, 0x6, 0xE, 0x9, 0xB, 0x3, 0x0, 0x8, 0x5, 0xC, 0xA},
+ },
+ {
+ {0x2, 0x8, 0xB, 0xD, 0xF, 0x7, 0x6, 0xE, 0x3, 0x1, 0x9, 0x4, 0x0, 0xA, 0xC, 0x5},
+ {0x1, 0xE, 0x2, 0xB, 0x4, 0xC, 0x3, 0x7, 0x6, 0xD, 0xA, 0x5, 0xF, 0x9, 0x0, 0x8},
+ {0x4, 0xC, 0x7, 0x5, 0x1, 0x6, 0x9, 0xA, 0x0, 0xE, 0xD, 0x8, 0x2, 0xB, 0x3, 0xF},
+ {0xB, 0x9, 0x5, 0x1, 0xC, 0x3, 0xD, 0xE, 0x6, 0x4, 0x7, 0xF, 0x2, 0x0, 0x8, 0xA},
+ },
+}
+
+// genSbox generates the variable sbox
+func genSbox(qi int, x byte) byte {
+ a0, b0 := x/16, x%16
+ for i := 0; i < 2; i++ {
+ a1 := a0 ^ b0
+ b1 := (a0 ^ ((b0 << 3) | (b0 >> 1)) ^ (a0 << 3)) & 15
+ a0 = qbox[qi][2*i][a1]
+ b0 = qbox[qi][2*i+1][b1]
+ }
+ return (b0 << 4) + a0
+}
+
+func TestSbox(t *testing.T) {
+ for n := range sbox {
+ for m := range sbox[n] {
+ if genSbox(n, byte(m)) != sbox[n][m] {
+ t.Errorf("#%d|%d: sbox value = %d want %d", n, m, sbox[n][m], genSbox(n, byte(m)))
+ }
+ }
+ }
+}
+
+var testVectors = []struct {
+ key []byte
+ dec []byte
+ enc []byte
+}{
+ // These tests are extracted from LibTom
+ {
+ []byte{0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A},
+ []byte{0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E, 0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19},
+ []byte{0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85, 0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3},
+ },
+ {
+ []byte{0x88, 0xB2, 0xB2, 0x70, 0x6B, 0x10, 0x5E, 0x36, 0xB4, 0x46, 0xBB, 0x6D, 0x73, 0x1A, 0x1E, 0x88,
+ 0xEF, 0xA7, 0x1F, 0x78, 0x89, 0x65, 0xBD, 0x44},
+ []byte{0x39, 0xDA, 0x69, 0xD6, 0xBA, 0x49, 0x97, 0xD5, 0x85, 0xB6, 0xDC, 0x07, 0x3C, 0xA3, 0x41, 0xB2},
+ []byte{0x18, 0x2B, 0x02, 0xD8, 0x14, 0x97, 0xEA, 0x45, 0xF9, 0xDA, 0xAC, 0xDC, 0x29, 0x19, 0x3A, 0x65},
+ },
+ {
+ []byte{0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D,
+ 0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F},
+ []byte{0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6},
+ []byte{0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA},
+ },
+ // These test are derived from http://www.schneier.com/code/ecb_ival.txt
+ {
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A},
+ },
+ {
+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ },
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xCF, 0xD1, 0xD2, 0xE5, 0xA9, 0xBE, 0x9C, 0xDF, 0x50, 0x1F, 0x13, 0xB8, 0x92, 0xBD, 0x22, 0x48},
+ },
+ {
+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
+ },
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x37, 0x52, 0x7B, 0xE0, 0x05, 0x23, 0x34, 0xB8, 0x9F, 0x0C, 0xFC, 0xCA, 0xE8, 0x7C, 0xFA, 0x20},
+ },
+}
+
+func TestCipher(t *testing.T) {
+ for n, tt := range testVectors {
+ // Test if the plaintext (dec) is encrypts to the given
+ // ciphertext (enc) using the given key. Test also if enc can
+ // be decrypted again into dec.
+ c, err := NewCipher(tt.key)
+ if err != nil {
+ t.Errorf("#%d: NewCipher: %v", n, err)
+ return
+ }
+
+ buf := make([]byte, 16)
+ c.Encrypt(buf, tt.dec)
+ if !bytes.Equal(buf, tt.enc) {
+ t.Errorf("#%d: encrypt = %x want %x", n, buf, tt.enc)
+ }
+ c.Decrypt(buf, tt.enc)
+ if !bytes.Equal(buf, tt.dec) {
+ t.Errorf("#%d: decrypt = %x want %x", n, buf, tt.dec)
+ }
+
+ // Test that 16 zero bytes, encrypted 1000 times then decrypted
+ // 1000 times results in zero bytes again.
+ zero := make([]byte, 16)
+ buf = make([]byte, 16)
+ for i := 0; i < 1000; i++ {
+ c.Encrypt(buf, buf)
+ }
+ for i := 0; i < 1000; i++ {
+ c.Decrypt(buf, buf)
+ }
+ if !bytes.Equal(buf, zero) {
+ t.Errorf("#%d: encrypt/decrypt 1000: have %x want %x", n, buf, zero)
+ }
+ }
+}
diff --git a/libgo/go/crypto/x509/x509.go b/libgo/go/crypto/x509/x509.go
index b7a527c..6199e8d 100644
--- a/libgo/go/crypto/x509/x509.go
+++ b/libgo/go/crypto/x509/x509.go
@@ -217,50 +217,40 @@ var (
oidPostalCode = []int{2, 5, 4, 17}
)
-func (n Name) toRDNSequence() (ret rdnSequence) {
- ret = make([]relativeDistinguishedNameSET, 9 /* maximum number of elements */ )
- i := 0
- if len(n.Country) > 0 {
- ret[i] = []attributeTypeAndValue{{oidCountry, n.Country}}
- i++
- }
- if len(n.Organization) > 0 {
- ret[i] = []attributeTypeAndValue{{oidOrganization, n.Organization}}
- i++
+// appendRDNs appends a relativeDistinguishedNameSET to the given rdnSequence
+// and returns the new value. The relativeDistinguishedNameSET contains an
+// attributeTypeAndValue for each of the given values. See RFC 5280, A.1, and
+// search for AttributeTypeAndValue.
+func appendRDNs(in rdnSequence, values []string, oid asn1.ObjectIdentifier) rdnSequence {
+ if len(values) == 0 {
+ return in
}
- if len(n.OrganizationalUnit) > 0 {
- ret[i] = []attributeTypeAndValue{{oidOrganizationalUnit, n.OrganizationalUnit}}
- i++
+
+ s := make([]attributeTypeAndValue, len(values))
+ for i, value := range values {
+ s[i].Type = oid
+ s[i].Value = value
}
+
+ return append(in, s)
+}
+
+func (n Name) toRDNSequence() (ret rdnSequence) {
+ ret = appendRDNs(ret, n.Country, oidCountry)
+ ret = appendRDNs(ret, n.Organization, oidOrganization)
+ ret = appendRDNs(ret, n.OrganizationalUnit, oidOrganizationalUnit)
+ ret = appendRDNs(ret, n.Locality, oidLocatity)
+ ret = appendRDNs(ret, n.Province, oidProvince)
+ ret = appendRDNs(ret, n.StreetAddress, oidStreetAddress)
+ ret = appendRDNs(ret, n.PostalCode, oidPostalCode)
if len(n.CommonName) > 0 {
- ret[i] = []attributeTypeAndValue{{oidCommonName, n.CommonName}}
- i++
+ ret = appendRDNs(ret, []string{n.CommonName}, oidCommonName)
}
if len(n.SerialNumber) > 0 {
- ret[i] = []attributeTypeAndValue{{oidSerialNumber, n.SerialNumber}}
- i++
+ ret = appendRDNs(ret, []string{n.SerialNumber}, oidSerialNumber)
}
- if len(n.Locality) > 0 {
- ret[i] = []attributeTypeAndValue{{oidLocatity, n.Locality}}
- i++
- }
- if len(n.Province) > 0 {
- ret[i] = []attributeTypeAndValue{{oidProvince, n.Province}}
- i++
- }
- if len(n.StreetAddress) > 0 {
- ret[i] = []attributeTypeAndValue{{oidStreetAddress, n.StreetAddress}}
- i++
- }
- if len(n.PostalCode) > 0 {
- ret[i] = []attributeTypeAndValue{{oidPostalCode, n.PostalCode}}
- i++
- }
-
- // Adding another RDN here? Remember to update the maximum number of
- // elements in the make() at the top of the function.
- return ret[0:i]
+ return ret
}
func getSignatureAlgorithmFromOID(oid []int) SignatureAlgorithm {
@@ -339,6 +329,8 @@ type Certificate struct {
// Subject Alternate Name values
DNSNames []string
EmailAddresses []string
+
+ PolicyIdentifiers []asn1.ObjectIdentifier
}
// UnsupportedAlgorithmError results from attempting to perform an operation
@@ -476,6 +468,12 @@ type rsaPublicKey struct {
E int
}
+// RFC 5280 4.2.1.4
+type policyInformation struct {
+ Policy asn1.ObjectIdentifier
+ // policyQualifiers omitted
+}
+
func parsePublicKey(algo PublicKeyAlgorithm, asn1Data []byte) (interface{}, os.Error) {
switch algo {
case RSA:
@@ -517,7 +515,7 @@ func parseCertificate(in *certificate) (*Certificate, os.Error) {
return nil, err
}
- out.Version = in.TBSCertificate.Version
+ out.Version = in.TBSCertificate.Version + 1
out.SerialNumber = in.TBSCertificate.SerialNumber.Bytes
out.Issuer.fillFromRDNSequence(&in.TBSCertificate.Issuer)
out.Subject.fillFromRDNSequence(&in.TBSCertificate.Subject)
@@ -623,6 +621,17 @@ func parseCertificate(in *certificate) (*Certificate, os.Error) {
}
out.SubjectKeyId = keyid
continue
+
+ case 32:
+ // RFC 5280 4.2.1.4: Certificate Policies
+ var policies []policyInformation
+ if _, err = asn1.Unmarshal(e.Value, &policies); err != nil {
+ return nil, err
+ }
+ out.PolicyIdentifiers = make([]asn1.ObjectIdentifier, len(policies))
+ for i, policy := range policies {
+ out.PolicyIdentifiers[i] = policy.Policy
+ }
}
}
@@ -683,15 +692,16 @@ func reverseBitsInAByte(in byte) byte {
}
var (
- oidExtensionSubjectKeyId = []int{2, 5, 29, 14}
- oidExtensionKeyUsage = []int{2, 5, 29, 15}
- oidExtensionAuthorityKeyId = []int{2, 5, 29, 35}
- oidExtensionBasicConstraints = []int{2, 5, 29, 19}
- oidExtensionSubjectAltName = []int{2, 5, 29, 17}
+ oidExtensionSubjectKeyId = []int{2, 5, 29, 14}
+ oidExtensionKeyUsage = []int{2, 5, 29, 15}
+ oidExtensionAuthorityKeyId = []int{2, 5, 29, 35}
+ oidExtensionBasicConstraints = []int{2, 5, 29, 19}
+ oidExtensionSubjectAltName = []int{2, 5, 29, 17}
+ oidExtensionCertificatePolicies = []int{2, 5, 29, 32}
)
func buildExtensions(template *Certificate) (ret []extension, err os.Error) {
- ret = make([]extension, 5 /* maximum number of elements. */ )
+ ret = make([]extension, 6 /* maximum number of elements. */ )
n := 0
if template.KeyUsage != 0 {
@@ -755,6 +765,19 @@ func buildExtensions(template *Certificate) (ret []extension, err os.Error) {
n++
}
+ if len(template.PolicyIdentifiers) > 0 {
+ ret[n].Id = oidExtensionCertificatePolicies
+ policies := make([]policyInformation, len(template.PolicyIdentifiers))
+ for i, policy := range template.PolicyIdentifiers {
+ policies[i].Policy = policy
+ }
+ ret[n].Value, err = asn1.Marshal(policies)
+ if err != nil {
+ return
+ }
+ n++
+ }
+
// Adding another extension here? Remember to update the maximum number
// of elements in the make() at the top of the function.
@@ -796,7 +819,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub *rsa.P
encodedPublicKey := asn1.BitString{BitLength: len(asn1PublicKey) * 8, Bytes: asn1PublicKey}
c := tbsCertificate{
- Version: 3,
+ Version: 2,
SerialNumber: asn1.RawValue{Bytes: template.SerialNumber, Tag: 2},
SignatureAlgorithm: algorithmIdentifier{oidSHA1WithRSA},
Issuer: parent.Subject.toRDNSequence(),
diff --git a/libgo/go/crypto/x509/x509_test.go b/libgo/go/crypto/x509/x509_test.go
index f667741d..2fe47fd 100644
--- a/libgo/go/crypto/x509/x509_test.go
+++ b/libgo/go/crypto/x509/x509_test.go
@@ -5,6 +5,7 @@
package x509
import (
+ "asn1"
"big"
"crypto/rand"
"crypto/rsa"
@@ -169,6 +170,8 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
BasicConstraintsValid: true,
IsCA: true,
DNSNames: []string{"test.example.com"},
+
+ PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}},
}
derBytes, err := CreateCertificate(random, &template, &template, &priv.PublicKey, priv)
@@ -182,6 +185,11 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
t.Errorf("Failed to parse certificate: %s", err)
return
}
+
+ 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)
+ }
+
err = cert.CheckSignatureFrom(cert)
if err != nil {
t.Errorf("Signature verification failed: %s", err)