From cdd7e02583325b05024cc1366a59eaafc09e1dc3 Mon Sep 17 00:00:00 2001 From: Adam Langley Date: Mon, 13 Feb 2012 12:38:45 -0500 Subject: [PATCH] crypto/...: more fixes for bug 2841 1) Remove the Reset() member in crypto/aes and crypto/des (and document the change). 2) Turn several empty error structures into vars. Any remaining error structures are either non-empty, or will probably become so in the future. 3) Implement SetWriteDeadline for TLS sockets. At the moment, the TLS status cannot be reused after a Write error, which is probably fine for most uses. 4) Make crypto/aes and crypto/des return a cipher.Block. R=rsc, r CC=golang-dev https://golang.org/cl/5625045 --- doc/go1.html | 221 +++++++------------------- doc/go1.tmpl | 221 +++++++------------------- src/pkg/crypto/aes/cipher.go | 42 ++--- src/pkg/crypto/cipher/cbc_aes_test.go | 7 +- src/pkg/crypto/cipher/cfb_test.go | 7 +- src/pkg/crypto/cipher/common_test.go | 2 +- src/pkg/crypto/cipher/ctr_aes_test.go | 7 +- src/pkg/crypto/cipher/ofb_test.go | 7 +- src/pkg/crypto/des/block.go | 2 +- src/pkg/crypto/des/cipher.go | 69 +++----- src/pkg/crypto/des/des_test.go | 16 +- src/pkg/crypto/dsa/dsa.go | 8 +- src/pkg/crypto/rand/rand_unix.go | 3 +- src/pkg/crypto/rsa/pkcs1v15.go | 14 +- src/pkg/crypto/rsa/rsa.go | 30 ++-- src/pkg/crypto/tls/conn.go | 31 ++-- src/pkg/crypto/x509/x509.go | 20 +-- 17 files changed, 226 insertions(+), 481 deletions(-) diff --git a/doc/go1.html b/doc/go1.html index 8ba97ad77b..8d01d96a6e 100644 --- a/doc/go1.html +++ b/doc/go1.html @@ -855,38 +855,23 @@ few programs beyond the need to run go fix. This category includes packages that are new in Go 1.

-

The bufio package

+

The crypto/aes and crypto/des packages

-In Go 1, bufio.NewReaderSize -and -bufio.NewWriterSize -functions no longer return an error for invalid sizes. -If the argument size is too small or invalid, it is adjusted. +In Go 1, the Reset method has been removed. Go does not guarantee +that memory is not copied and therefore this method was misleading.

-Updating: -What little code is affected will be caught by the compiler and must be updated by hand. -

- -

The compress/flate, compress/gzip and compress/zlib packages

- -

-In Go 1, the NewWriterXxx functions in -compress/flate, -compress/gzip and -compress/zlib -all return (*Writer, error) if they take a compression level, -and *Writer otherwise. Package gzip's -Compressor and Decompressor types have been renamed -to Writer and Reader. Package flate's -WrongValueError type has been removed. +The cipher-specific types *aes.Cipher, *des.Cipher, +and *des.TripleDESCipher have been removed in favor of +cipher.Block.

Updating: -What little code is affected will be caught by the compiler and must be updated by hand. +Remove the calls to Reset. Replace uses of the specific cipher types with +cipher.Block.

The crypto/elliptic package

@@ -939,64 +924,6 @@ to be implemented in the future. No changes will be needed.

-

The encoding/binary package

- -

-In Go 1, the binary.TotalSize function has been replaced by -Size, -which takes an interface{} argument rather than -a reflect.Value. -

- -

-Updating: -What little code is affected will be caught by the compiler and must be updated by hand. -

- -

The encoding/xml package

- -

-In Go 1, the xml package -has been brought closer in design to the other marshaling packages such -as encoding/gob. -

- -

-The old Parser type is renamed -Decoder and has a new -Decode method. An -Encoder type was also -introduced. -

- -

-The functions Marshal -and Unmarshal -work with []byte values now. To work with streams, -use the new Encoder -and Decoder types. -

- -

-When marshaling or unmarshaling values, the format of supported flags in -field tags has changed to be closer to the -json package -(`xml:"name,flag"`). The matching done between field tags, field -names, and the XML attribute and element names is now case-sensitive. -The XMLName field tag, if present, must also match the name -of the XML element being marshaled. -

- -

-Updating: -Running go fix will update most uses of the package except for some calls to -Unmarshal. Special care must be taken with field tags, -since the fix tool will not update them and if not fixed by hand they will -misbehave silently in some cases. For example, the old -"attr" is now written ",attr" while plain -"attr" remains valid but with a different meaning. -

-

The expvar package

@@ -1046,15 +973,6 @@ The Duration flag is new and affects no existing code. Several packages under go have slightly revised APIs.

-

-A concrete Mode type was introduced for configuration mode flags -in the packages -go/scanner, -go/parser, -go/printer, and -go/doc. -

-

The modes AllowIllegalChars and InsertSemis have been removed from the go/scanner package. They were mostly @@ -1063,16 +981,6 @@ useful for scanning text other then Go source files. Instead, the for that purpose.

-

-The ErrorHandler provided -to the scanner's Init method is -now simply a function rather than an interface. The ErrorVector type has -been removed in favor of the (existing) ErrorList -type, and the ErrorVector methods have been migrated. Instead of embedding -an ErrorVector in a client of the scanner, now a client should maintain -an ErrorList. -

-

The set of parse functions provided by the go/parser package has been reduced to the primary parse function @@ -1081,17 +989,6 @@ convenience functions ParseDirParseExpr.

-

-The go/printer package supports an additional -configuration mode SourcePos; -if set, the printer will emit //line comments such that the generated -output contains the original source code position information. The new type -CommentedNode can be -used to provide comments associated with an arbitrary -ast.Node (until now only -ast.File carried comment information). -

-

The type names of the go/doc package have been streamlined by removing the Doc suffix: PackageDoc @@ -1189,16 +1086,10 @@ The affected items are:

-The Request.RawURL field has been removed; it was a +Also, the Request.RawURL field has been removed; it was a historical artifact.

-

-The Handle and HandleFunc -functions, and the similarly-named methods of ServeMux, -now panic if an attempt is made to register the same pattern twice. -

-

Updating: Running go fix will update the few programs that are affected except for @@ -1235,7 +1126,9 @@ packages. The old image.ColorImage type is still in the image package but has been renamed image.Uniform, -while image.Tiled has been removed. +while image.Tiled +has been renamed +image.Repeated.

@@ -1296,6 +1189,7 @@ This table lists the renamings.


image.ColorImage image.Uniform +image.Tiled image.Repeated

@@ -1320,18 +1214,6 @@ and Running go fix will update almost all code affected by the change.

-

The log/syslog package

- -

-In Go 1, the syslog.NewLogger -function returns an error as well as a log.Logger. -

- -

-Updating: -What little code is affected will be caught by the compiler and must be updated by hand. -

-

The mime package

@@ -1378,27 +1260,7 @@ Code that uses the old methods will fail to compile and must be updated by hand. The semantic change makes it difficult for the fix tool to update automatically.

-

The os package

- -

The Time function has been removed; callers should use -the Time type from the -time package.

- -

The Exec function has been removed; callers should use -Exec from the syscall package, where available.

- -

The ShellExpand function has been renamed to ExpandEnv.

- -

The NewFile function -now takes a uintptr fd, instead of an int. -The Fd method on files now -also returns a uintptr.

- -

Updating: Code will fail to compile and must be updated -by hand.

- -

The os.FileInfo type

+

The os.FileInfo type

Go 1 redefines the os.FileInfo type, @@ -1639,17 +1501,6 @@ Existing code is unaffected, although benchmarks that use println or panic should be updated to use the new methods.

-

The testing/script package

- -

-The testing/script package has been deleted. It was a dreg. -

- -

-Updating: -No code is likely to be affected. -

-

The url package

@@ -1718,6 +1569,50 @@ Code that uses the old fields will fail to compile and must be updated by hand. The semantic changes make it difficult for the fix tool to update automatically.

+

The xml package

+ +

+In Go 1, the xml package +has been brought closer in design to the other marshaling packages such +as encoding/gob. +

+ +

+The old Parser type is renamed +Decoder and has a new +Decode method. An +Encoder type was also +introduced. +

+ +

+The functions Marshal +and Unmarshal +work with []byte values now. To work with streams, +use the new Encoder +and Decoder types. +

+ +

+When marshaling or unmarshaling values, the format of supported flags in +field tags has changed to be closer to the +json package +(`xml:"name,flag"`). The matching done between field tags, field +names, and the XML attribute and element names is now case-sensitive. +The XMLName field tag, if present, must also match the name +of the XML element being marshaled. +

+ +

+Updating: +Running go fix will update most uses of the package except for some calls to +Unmarshal. Special care must be taken with field tags, +since the fix tool will not update them and if not fixed by hand they will +misbehave silently in some cases. For example, the old +"attr" is now written ",attr" while plain +"attr" remains valid but with a different meaning. +

+

The go command

Packaged releases

diff --git a/doc/go1.tmpl b/doc/go1.tmpl index bda9ef48dd..0f23864ccc 100644 --- a/doc/go1.tmpl +++ b/doc/go1.tmpl @@ -759,38 +759,23 @@ few programs beyond the need to run go fix. This category includes packages that are new in Go 1.

-

The bufio package

+

The crypto/aes and crypto/des packages

-In Go 1, bufio.NewReaderSize -and -bufio.NewWriterSize -functions no longer return an error for invalid sizes. -If the argument size is too small or invalid, it is adjusted. +In Go 1, the Reset method has been removed. Go does not guarantee +that memory is not copied and therefore this method was misleading.

-Updating: -What little code is affected will be caught by the compiler and must be updated by hand. -

- -

The compress/flate, compress/gzip and compress/zlib packages

- -

-In Go 1, the NewWriterXxx functions in -compress/flate, -compress/gzip and -compress/zlib -all return (*Writer, error) if they take a compression level, -and *Writer otherwise. Package gzip's -Compressor and Decompressor types have been renamed -to Writer and Reader. Package flate's -WrongValueError type has been removed. +The cipher-specific types *aes.Cipher, *des.Cipher, +and *des.TripleDESCipher have been removed in favor of +cipher.Block.

Updating: -What little code is affected will be caught by the compiler and must be updated by hand. +Remove the calls to Reset. Replace uses of the specific cipher types with +cipher.Block.

The crypto/elliptic package

@@ -843,64 +828,6 @@ to be implemented in the future. No changes will be needed.

-

The encoding/binary package

- -

-In Go 1, the binary.TotalSize function has been replaced by -Size, -which takes an interface{} argument rather than -a reflect.Value. -

- -

-Updating: -What little code is affected will be caught by the compiler and must be updated by hand. -

- -

The encoding/xml package

- -

-In Go 1, the xml package -has been brought closer in design to the other marshaling packages such -as encoding/gob. -

- -

-The old Parser type is renamed -Decoder and has a new -Decode method. An -Encoder type was also -introduced. -

- -

-The functions Marshal -and Unmarshal -work with []byte values now. To work with streams, -use the new Encoder -and Decoder types. -

- -

-When marshaling or unmarshaling values, the format of supported flags in -field tags has changed to be closer to the -json package -(`xml:"name,flag"`). The matching done between field tags, field -names, and the XML attribute and element names is now case-sensitive. -The XMLName field tag, if present, must also match the name -of the XML element being marshaled. -

- -

-Updating: -Running go fix will update most uses of the package except for some calls to -Unmarshal. Special care must be taken with field tags, -since the fix tool will not update them and if not fixed by hand they will -misbehave silently in some cases. For example, the old -"attr" is now written ",attr" while plain -"attr" remains valid but with a different meaning. -

-

The expvar package

@@ -949,15 +876,6 @@ The Duration flag is new and affects no existing code. Several packages under go have slightly revised APIs.

-

-A concrete Mode type was introduced for configuration mode flags -in the packages -go/scanner, -go/parser, -go/printer, and -go/doc. -

-

The modes AllowIllegalChars and InsertSemis have been removed from the go/scanner package. They were mostly @@ -966,16 +884,6 @@ useful for scanning text other then Go source files. Instead, the for that purpose.

-

-The ErrorHandler provided -to the scanner's Init method is -now simply a function rather than an interface. The ErrorVector type has -been removed in favor of the (existing) ErrorList -type, and the ErrorVector methods have been migrated. Instead of embedding -an ErrorVector in a client of the scanner, now a client should maintain -an ErrorList. -

-

The set of parse functions provided by the go/parser package has been reduced to the primary parse function @@ -984,17 +892,6 @@ convenience functions ParseDirParseExpr.

-

-The go/printer package supports an additional -configuration mode SourcePos; -if set, the printer will emit //line comments such that the generated -output contains the original source code position information. The new type -CommentedNode can be -used to provide comments associated with an arbitrary -ast.Node (until now only -ast.File carried comment information). -

-

The type names of the go/doc package have been streamlined by removing the Doc suffix: PackageDoc @@ -1092,16 +989,10 @@ The affected items are:

-The Request.RawURL field has been removed; it was a +Also, the Request.RawURL field has been removed; it was a historical artifact.

-

-The Handle and HandleFunc -functions, and the similarly-named methods of ServeMux, -now panic if an attempt is made to register the same pattern twice. -

-

Updating: Running go fix will update the few programs that are affected except for @@ -1138,7 +1029,9 @@ packages. The old image.ColorImage type is still in the image package but has been renamed image.Uniform, -while image.Tiled has been removed. +while image.Tiled +has been renamed +image.Repeated.

@@ -1199,6 +1092,7 @@ This table lists the renamings.


image.ColorImage image.Uniform +image.Tiled image.Repeated

@@ -1223,18 +1117,6 @@ and Running go fix will update almost all code affected by the change.

-

The log/syslog package

- -

-In Go 1, the syslog.NewLogger -function returns an error as well as a log.Logger. -

- -

-Updating: -What little code is affected will be caught by the compiler and must be updated by hand. -

-

The mime package

@@ -1281,27 +1163,7 @@ Code that uses the old methods will fail to compile and must be updated by hand. The semantic change makes it difficult for the fix tool to update automatically.

-

The os package

- -

The Time function has been removed; callers should use -the Time type from the -time package.

- -

The Exec function has been removed; callers should use -Exec from the syscall package, where available.

- -

The ShellExpand function has been renamed to ExpandEnv.

- -

The NewFile function -now takes a uintptr fd, instead of an int. -The Fd method on files now -also returns a uintptr.

- -

Updating: Code will fail to compile and must be updated -by hand.

- -

The os.FileInfo type

+

The os.FileInfo type

Go 1 redefines the os.FileInfo type, @@ -1529,17 +1391,6 @@ Existing code is unaffected, although benchmarks that use println or panic should be updated to use the new methods.

-

The testing/script package

- -

-The testing/script package has been deleted. It was a dreg. -

- -

-Updating: -No code is likely to be affected. -

-

The url package

@@ -1608,6 +1459,50 @@ Code that uses the old fields will fail to compile and must be updated by hand. The semantic changes make it difficult for the fix tool to update automatically.

+

The xml package

+ +

+In Go 1, the xml package +has been brought closer in design to the other marshaling packages such +as encoding/gob. +

+ +

+The old Parser type is renamed +Decoder and has a new +Decode method. An +Encoder type was also +introduced. +

+ +

+The functions Marshal +and Unmarshal +work with []byte values now. To work with streams, +use the new Encoder +and Decoder types. +

+ +

+When marshaling or unmarshaling values, the format of supported flags in +field tags has changed to be closer to the +json package +(`xml:"name,flag"`). The matching done between field tags, field +names, and the XML attribute and element names is now case-sensitive. +The XMLName field tag, if present, must also match the name +of the XML element being marshaled. +

+ +

+Updating: +Running go fix will update most uses of the package except for some calls to +Unmarshal. Special care must be taken with field tags, +since the fix tool will not update them and if not fixed by hand they will +misbehave silently in some cases. For example, the old +"attr" is now written ",attr" while plain +"attr" remains valid but with a different meaning. +

+

The go command

Packaged releases

diff --git a/src/pkg/crypto/aes/cipher.go b/src/pkg/crypto/aes/cipher.go index 28752e7361..7d307c93a0 100644 --- a/src/pkg/crypto/aes/cipher.go +++ b/src/pkg/crypto/aes/cipher.go @@ -4,13 +4,16 @@ package aes -import "strconv" +import ( + "crypto/cipher" + "strconv" +) // The AES block size in bytes. const BlockSize = 16 -// A Cipher is an instance of AES encryption using a particular key. -type Cipher struct { +// A cipher is an instance of AES encryption using a particular key. +type aesCipher struct { enc []uint32 dec []uint32 } @@ -21,11 +24,11 @@ func (k KeySizeError) Error() string { return "crypto/aes: invalid key size " + strconv.Itoa(int(k)) } -// NewCipher creates and returns a new Cipher. +// NewCipher creates and returns a new cipher.Block. // The key argument should be the AES key, // either 16, 24, or 32 bytes to select // AES-128, AES-192, or AES-256. -func NewCipher(key []byte) (*Cipher, error) { +func NewCipher(key []byte) (cipher.Block, error) { k := len(key) switch k { default: @@ -35,34 +38,13 @@ func NewCipher(key []byte) (*Cipher, error) { } n := k + 28 - c := &Cipher{make([]uint32, n), make([]uint32, n)} + c := &aesCipher{make([]uint32, n), make([]uint32, n)} expandKey(key, c.enc, c.dec) return c, nil } -// BlockSize returns the AES block size, 16 bytes. -// It is necessary to satisfy the Block interface in the -// package "crypto/cipher". -func (c *Cipher) BlockSize() int { return BlockSize } +func (c *aesCipher) BlockSize() int { return BlockSize } -// Encrypt encrypts the 16-byte buffer src using the key k -// and stores the result in dst. -// 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/cipher/cbc.go). -func (c *Cipher) Encrypt(dst, src []byte) { encryptBlock(c.enc, dst, src) } +func (c *aesCipher) Encrypt(dst, src []byte) { encryptBlock(c.enc, dst, src) } -// Decrypt decrypts the 16-byte buffer src using the key k -// and stores the result in dst. -func (c *Cipher) Decrypt(dst, src []byte) { decryptBlock(c.dec, dst, src) } - -// Reset zeros the key data, so that it will no longer -// appear in the process's memory. -func (c *Cipher) Reset() { - for i := 0; i < len(c.enc); i++ { - c.enc[i] = 0 - } - for i := 0; i < len(c.dec); i++ { - c.dec[i] = 0 - } -} +func (c *aesCipher) Decrypt(dst, src []byte) { decryptBlock(c.dec, dst, src) } diff --git a/src/pkg/crypto/cipher/cbc_aes_test.go b/src/pkg/crypto/cipher/cbc_aes_test.go index 944ca1ba85..cee3a784b5 100644 --- a/src/pkg/crypto/cipher/cbc_aes_test.go +++ b/src/pkg/crypto/cipher/cbc_aes_test.go @@ -8,11 +8,12 @@ // Special Publication 800-38A, ``Recommendation for Block Cipher // Modes of Operation,'' 2001 Edition, pp. 24-29. -package cipher +package cipher_test import ( "bytes" "crypto/aes" + "crypto/cipher" "testing" ) @@ -72,14 +73,14 @@ func TestCBC_AES(t *testing.T) { continue } - encrypter := NewCBCEncrypter(c, tt.iv) + encrypter := cipher.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) } - decrypter := NewCBCDecrypter(c, tt.iv) + decrypter := cipher.NewCBCDecrypter(c, tt.iv) p := make([]byte, len(d)) decrypter.CryptBlocks(p, d) if !bytes.Equal(tt.in, p) { diff --git a/src/pkg/crypto/cipher/cfb_test.go b/src/pkg/crypto/cipher/cfb_test.go index 9547bfceb7..f704b337e4 100644 --- a/src/pkg/crypto/cipher/cfb_test.go +++ b/src/pkg/crypto/cipher/cfb_test.go @@ -2,11 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package cipher +package cipher_test import ( "bytes" "crypto/aes" + "crypto/cipher" "crypto/rand" "testing" ) @@ -21,11 +22,11 @@ func TestCFB(t *testing.T) { plaintext := []byte("this is the plaintext") iv := make([]byte, block.BlockSize()) rand.Reader.Read(iv) - cfb := NewCFBEncrypter(block, iv) + cfb := cipher.NewCFBEncrypter(block, iv) ciphertext := make([]byte, len(plaintext)) cfb.XORKeyStream(ciphertext, plaintext) - cfbdec := NewCFBDecrypter(block, iv) + cfbdec := cipher.NewCFBDecrypter(block, iv) plaintextCopy := make([]byte, len(plaintext)) cfbdec.XORKeyStream(plaintextCopy, ciphertext) diff --git a/src/pkg/crypto/cipher/common_test.go b/src/pkg/crypto/cipher/common_test.go index fb755757c2..c75c919d17 100644 --- a/src/pkg/crypto/cipher/common_test.go +++ b/src/pkg/crypto/cipher/common_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package cipher +package cipher_test // Common values for tests. diff --git a/src/pkg/crypto/cipher/ctr_aes_test.go b/src/pkg/crypto/cipher/ctr_aes_test.go index 8dca9968c4..d019ae0d02 100644 --- a/src/pkg/crypto/cipher/ctr_aes_test.go +++ b/src/pkg/crypto/cipher/ctr_aes_test.go @@ -8,11 +8,12 @@ // Special Publication 800-38A, ``Recommendation for Block Cipher // Modes of Operation,'' 2001 Edition, pp. 55-58. -package cipher +package cipher_test import ( "bytes" "crypto/aes" + "crypto/cipher" "testing" ) @@ -76,7 +77,7 @@ func TestCTR_AES(t *testing.T) { for j := 0; j <= 5; j += 5 { in := tt.in[0 : len(tt.in)-j] - ctr := NewCTR(c, tt.iv) + ctr := cipher.NewCTR(c, tt.iv) encrypted := make([]byte, len(in)) ctr.XORKeyStream(encrypted, in) if out := tt.out[0:len(in)]; !bytes.Equal(out, encrypted) { @@ -86,7 +87,7 @@ func TestCTR_AES(t *testing.T) { for j := 0; j <= 7; j += 7 { in := tt.out[0 : len(tt.out)-j] - ctr := NewCTR(c, tt.iv) + ctr := cipher.NewCTR(c, tt.iv) plain := make([]byte, len(in)) ctr.XORKeyStream(plain, in) if out := tt.in[0:len(in)]; !bytes.Equal(out, plain) { diff --git a/src/pkg/crypto/cipher/ofb_test.go b/src/pkg/crypto/cipher/ofb_test.go index 9b4495c883..8d3c5d3a38 100644 --- a/src/pkg/crypto/cipher/ofb_test.go +++ b/src/pkg/crypto/cipher/ofb_test.go @@ -8,11 +8,12 @@ // Special Publication 800-38A, ``Recommendation for Block Cipher // Modes of Operation,'' 2001 Edition, pp. 52-55. -package cipher +package cipher_test import ( "bytes" "crypto/aes" + "crypto/cipher" "testing" ) @@ -76,7 +77,7 @@ func TestOFB(t *testing.T) { for j := 0; j <= 5; j += 5 { plaintext := tt.in[0 : len(tt.in)-j] - ofb := NewOFB(c, tt.iv) + ofb := cipher.NewOFB(c, tt.iv) ciphertext := make([]byte, len(plaintext)) ofb.XORKeyStream(ciphertext, plaintext) if !bytes.Equal(ciphertext, tt.out[:len(plaintext)]) { @@ -86,7 +87,7 @@ func TestOFB(t *testing.T) { for j := 0; j <= 5; j += 5 { ciphertext := tt.out[0 : len(tt.in)-j] - ofb := NewOFB(c, tt.iv) + ofb := cipher.NewOFB(c, tt.iv) plaintext := make([]byte, len(ciphertext)) ofb.XORKeyStream(plaintext, ciphertext) if !bytes.Equal(plaintext, tt.in[:len(ciphertext)]) { diff --git a/src/pkg/crypto/des/block.go b/src/pkg/crypto/des/block.go index e18eaedf58..c11c62cd72 100644 --- a/src/pkg/crypto/des/block.go +++ b/src/pkg/crypto/des/block.go @@ -79,7 +79,7 @@ func ksRotate(in uint32) (out []uint32) { } // creates 16 56-bit subkeys from the original key -func (c *Cipher) generateSubkeys(keyBytes []byte) { +func (c *desCipher) generateSubkeys(keyBytes []byte) { // apply PC1 permutation to key key := binary.BigEndian.Uint64(keyBytes) permutedKey := permuteBlock(key, permutedChoice1[:]) diff --git a/src/pkg/crypto/des/cipher.go b/src/pkg/crypto/des/cipher.go index 1c41e29a8b..2f929ca7be 100644 --- a/src/pkg/crypto/des/cipher.go +++ b/src/pkg/crypto/des/cipher.go @@ -4,7 +4,10 @@ package des -import "strconv" +import ( + "crypto/cipher" + "strconv" +) // The DES block size in bytes. const BlockSize = 8 @@ -15,86 +18,56 @@ func (k KeySizeError) Error() string { return "crypto/des: invalid key size " + strconv.Itoa(int(k)) } -// Cipher is an instance of DES encryption. -type Cipher struct { +// desCipher is an instance of DES encryption. +type desCipher struct { subkeys [16]uint64 } -// NewCipher creates and returns a new Cipher. -func NewCipher(key []byte) (*Cipher, error) { +// NewCipher creates and returns a new cipher.Block. +func NewCipher(key []byte) (cipher.Block, error) { if len(key) != 8 { return nil, KeySizeError(len(key)) } - c := new(Cipher) + c := new(desCipher) c.generateSubkeys(key) return c, nil } -// BlockSize returns the DES block size, 8 bytes. -func (c *Cipher) BlockSize() int { return BlockSize } +func (c *desCipher) BlockSize() int { return BlockSize } -// Encrypt encrypts the 8-byte buffer src and stores the result in dst. -// 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/cipher/cbc.go). -func (c *Cipher) Encrypt(dst, src []byte) { encryptBlock(c.subkeys[:], dst, src) } +func (c *desCipher) Encrypt(dst, src []byte) { encryptBlock(c.subkeys[:], dst, src) } -// Decrypt decrypts the 8-byte buffer src and stores the result in dst. -func (c *Cipher) Decrypt(dst, src []byte) { decryptBlock(c.subkeys[:], dst, src) } +func (c *desCipher) Decrypt(dst, src []byte) { decryptBlock(c.subkeys[:], dst, src) } -// Reset zeros the key data, so that it will no longer -// appear in the process's memory. -func (c *Cipher) Reset() { - for i := 0; i < len(c.subkeys); i++ { - c.subkeys[i] = 0 - } -} - -// A TripleDESCipher is an instance of TripleDES encryption. -type TripleDESCipher struct { - cipher1, cipher2, cipher3 Cipher +// A tripleDESCipher is an instance of TripleDES encryption. +type tripleDESCipher struct { + cipher1, cipher2, cipher3 desCipher } -// NewCipher creates and returns a new Cipher. -func NewTripleDESCipher(key []byte) (*TripleDESCipher, error) { +// NewTripleDESCipher creates and returns a new cipher.Block. +func NewTripleDESCipher(key []byte) (cipher.Block, error) { if len(key) != 24 { return nil, KeySizeError(len(key)) } - c := new(TripleDESCipher) + c := new(tripleDESCipher) c.cipher1.generateSubkeys(key[:8]) c.cipher2.generateSubkeys(key[8:16]) c.cipher3.generateSubkeys(key[16:]) return c, nil } -// BlockSize returns the TripleDES block size, 8 bytes. -// It is necessary to satisfy the Block interface in the -// package "crypto/cipher". -func (c *TripleDESCipher) BlockSize() int { return BlockSize } +func (c *tripleDESCipher) BlockSize() int { return BlockSize } -// Encrypts the 8-byte buffer src and stores the result in dst. -// 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/cipher/cbc.go). -func (c *TripleDESCipher) Encrypt(dst, src []byte) { +func (c *tripleDESCipher) Encrypt(dst, src []byte) { c.cipher1.Encrypt(dst, src) c.cipher2.Decrypt(dst, dst) c.cipher3.Encrypt(dst, dst) } -// Decrypts the 8-byte buffer src and stores the result in dst. -func (c *TripleDESCipher) Decrypt(dst, src []byte) { +func (c *tripleDESCipher) Decrypt(dst, src []byte) { c.cipher3.Decrypt(dst, src) c.cipher2.Encrypt(dst, dst) c.cipher1.Decrypt(dst, dst) } - -// Reset zeros the key data, so that it will no longer -// appear in the process's memory. -func (c *TripleDESCipher) Reset() { - c.cipher1.Reset() - c.cipher2.Reset() - c.cipher3.Reset() -} diff --git a/src/pkg/crypto/des/des_test.go b/src/pkg/crypto/des/des_test.go index d1f3aa71ac..e9fc236299 100644 --- a/src/pkg/crypto/des/des_test.go +++ b/src/pkg/crypto/des/des_test.go @@ -1260,11 +1260,19 @@ var tableA4Tests = []CryptTest{ []byte{0x63, 0xfa, 0xc0, 0xd0, 0x34, 0xd9, 0xf7, 0x93}}, } +func newCipher(key []byte) *desCipher { + c, err := NewCipher(key) + if err != nil { + panic("NewCipher failed: " + err.Error()) + } + return c.(*desCipher) +} + // Use the known weak keys to test DES implementation func TestWeakKeys(t *testing.T) { for i, tt := range weakKeyTests { var encrypt = func(in []byte) (out []byte) { - c, _ := NewCipher(tt.key) + c := newCipher(tt.key) out = make([]byte, len(in)) encryptBlock(c.subkeys[:], out, in) return @@ -1285,7 +1293,7 @@ func TestWeakKeys(t *testing.T) { func TestSemiWeakKeyPairs(t *testing.T) { for i, tt := range semiWeakKeyTests { var encrypt = func(key, in []byte) (out []byte) { - c, _ := NewCipher(key) + c := newCipher(key) out = make([]byte, len(in)) encryptBlock(c.subkeys[:], out, in) return @@ -1305,7 +1313,7 @@ func TestSemiWeakKeyPairs(t *testing.T) { func TestDESEncryptBlock(t *testing.T) { for i, tt := range encryptDESTests { - c, _ := NewCipher(tt.key) + c := newCipher(tt.key) out := make([]byte, len(tt.in)) encryptBlock(c.subkeys[:], out, tt.in) @@ -1317,7 +1325,7 @@ func TestDESEncryptBlock(t *testing.T) { func TestDESDecryptBlock(t *testing.T) { for i, tt := range encryptDESTests { - c, _ := NewCipher(tt.key) + c := newCipher(tt.key) plain := make([]byte, len(tt.in)) decryptBlock(c.subkeys[:], plain, tt.out) diff --git a/src/pkg/crypto/dsa/dsa.go b/src/pkg/crypto/dsa/dsa.go index 81487f68f4..f7c4783179 100644 --- a/src/pkg/crypto/dsa/dsa.go +++ b/src/pkg/crypto/dsa/dsa.go @@ -29,17 +29,11 @@ type PrivateKey struct { X *big.Int } -type invalidPublicKeyError int - -func (invalidPublicKeyError) Error() string { - return "crypto/dsa: invalid public key" -} - // ErrInvalidPublicKey results when a public key is not usable by this code. // FIPS is quite strict about the format of DSA keys, but other code may be // less so. Thus, when using keys which may have been generated by other code, // this error must be handled. -var ErrInvalidPublicKey error = invalidPublicKeyError(0) +var ErrInvalidPublicKey = errors.New("crypto/dsa: invalid public key") // ParameterSizes is a enumeration of the acceptable bit lengths of the primes // in a set of DSA parameters. See FIPS 186-3, section 4.2. diff --git a/src/pkg/crypto/rand/rand_unix.go b/src/pkg/crypto/rand/rand_unix.go index 5d4fc8198a..5eb4cda2b3 100644 --- a/src/pkg/crypto/rand/rand_unix.go +++ b/src/pkg/crypto/rand/rand_unix.go @@ -12,6 +12,7 @@ package rand import ( "bufio" "crypto/aes" + "crypto/cipher" "io" "os" "sync" @@ -66,7 +67,7 @@ func newReader(entropy io.Reader) io.Reader { type reader struct { mu sync.Mutex budget int // number of bytes that can be generated - cipher *aes.Cipher + cipher cipher.Block entropy io.Reader time, seed, dst, key [aes.BlockSize]byte } diff --git a/src/pkg/crypto/rsa/pkcs1v15.go b/src/pkg/crypto/rsa/pkcs1v15.go index 4f12cbea5c..254f4a3da0 100644 --- a/src/pkg/crypto/rsa/pkcs1v15.go +++ b/src/pkg/crypto/rsa/pkcs1v15.go @@ -21,7 +21,7 @@ import ( func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, err error) { k := (pub.N.BitLen() + 7) / 8 if len(msg) > k-11 { - err = MessageTooLongError{} + err = ErrMessageTooLong return } @@ -47,7 +47,7 @@ func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, er func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out []byte, err error) { valid, out, err := decryptPKCS1v15(rand, priv, ciphertext) if err == nil && valid == 0 { - err = DecryptionError{} + err = ErrDecryption } return @@ -69,7 +69,7 @@ func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out [ func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) (err error) { k := (priv.N.BitLen() + 7) / 8 if k-(len(key)+3+8) < 0 { - err = DecryptionError{} + err = ErrDecryption return } @@ -86,7 +86,7 @@ func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []by func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid int, msg []byte, err error) { k := (priv.N.BitLen() + 7) / 8 if k < 11 { - err = DecryptionError{} + err = ErrDecryption return } @@ -170,7 +170,7 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []b tLen := len(prefix) + hashLen k := (priv.N.BitLen() + 7) / 8 if k < tLen+11 { - return nil, MessageTooLongError{} + return nil, ErrMessageTooLong } // EM = 0x00 || 0x01 || PS || 0x00 || T @@ -203,7 +203,7 @@ func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) tLen := len(prefix) + hashLen k := (pub.N.BitLen() + 7) / 8 if k < tLen+11 { - err = VerificationError{} + err = ErrVerification return } @@ -223,7 +223,7 @@ func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) } if ok != 1 { - return VerificationError{} + return ErrVerification } return nil diff --git a/src/pkg/crypto/rsa/rsa.go b/src/pkg/crypto/rsa/rsa.go index 677d27be5d..ec77e68696 100644 --- a/src/pkg/crypto/rsa/rsa.go +++ b/src/pkg/crypto/rsa/rsa.go @@ -206,13 +206,9 @@ func mgf1XOR(out []byte, hash hash.Hash, seed []byte) { } } -// MessageTooLongError is returned when attempting to encrypt a message which -// is too large for the size of the public key. -type MessageTooLongError struct{} - -func (MessageTooLongError) Error() string { - return "message too long for RSA public key size" -} +// ErrMessageTooLong is returned when attempting to encrypt a message which is +// too large for the size of the public key. +var ErrMessageTooLong = errors.New("crypto/rsa: message too long for RSA public key size") func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int { e := big.NewInt(int64(pub.E)) @@ -227,7 +223,7 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l hash.Reset() k := (pub.N.BitLen() + 7) / 8 if len(msg) > k-2*hash.Size()-2 { - err = MessageTooLongError{} + err = ErrMessageTooLong return } @@ -266,17 +262,13 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l return } -// A DecryptionError represents a failure to decrypt a message. +// ErrDecryption represents a failure to decrypt a message. // It is deliberately vague to avoid adaptive attacks. -type DecryptionError struct{} +var ErrDecryption = errors.New("crypto/rsa: decryption error") -func (DecryptionError) Error() string { return "RSA decryption error" } - -// A VerificationError represents a failure to verify a signature. +// ErrVerification represents a failure to verify a signature. // It is deliberately vague to avoid adaptive attacks. -type VerificationError struct{} - -func (VerificationError) Error() string { return "RSA verification error" } +var ErrVerification = errors.New("crypto/rsa: verification error") // modInverse returns ia, the inverse of a in the multiplicative group of prime // order n. It requires that a be a member of the group (i.e. less than n). @@ -338,7 +330,7 @@ func (priv *PrivateKey) Precompute() { func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err error) { // TODO(agl): can we get away with reusing blinds? if c.Cmp(priv.N) > 0 { - err = DecryptionError{} + err = ErrDecryption return } @@ -417,7 +409,7 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext k := (priv.N.BitLen() + 7) / 8 if len(ciphertext) > k || k < hash.Size()*2+2 { - err = DecryptionError{} + err = ErrDecryption return } @@ -473,7 +465,7 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext } if firstByteIsZero&lHash2Good&^invalid&^lookingForIndex != 1 { - err = DecryptionError{} + err = ErrDecryption return } diff --git a/src/pkg/crypto/tls/conn.go b/src/pkg/crypto/tls/conn.go index e6cee1278c..2a5115dc6a 100644 --- a/src/pkg/crypto/tls/conn.go +++ b/src/pkg/crypto/tls/conn.go @@ -87,9 +87,9 @@ func (c *Conn) RemoteAddr() net.Addr { return c.conn.RemoteAddr() } -// SetDeadline sets the read deadline associated with the connection. -// There is no write deadline. -// A zero value for t means Read will not time out. +// SetDeadline sets the read and write deadlines associated with the connection. +// A zero value for t means Read and Write will not time out. +// After a Write has timed out, the TLS state is corrupt and all future writes will return the same error. func (c *Conn) SetDeadline(t time.Time) error { return c.conn.SetDeadline(t) } @@ -100,10 +100,11 @@ func (c *Conn) SetReadDeadline(t time.Time) error { return c.conn.SetReadDeadline(t) } -// SetWriteDeadline exists to satisfy the net.Conn interface -// but is not implemented by TLS. It always returns an error. +// SetWriteDeadline sets the write deadline on the underlying conneciton. +// A zero value for t means Write will not time out. +// After a Write has timed out, the TLS state is corrupt and all future writes will return the same error. func (c *Conn) SetWriteDeadline(t time.Time) error { - return errors.New("TLS does not support SetWriteDeadline") + return c.conn.SetWriteDeadline(t) } // A halfConn represents one direction of the record layer @@ -726,9 +727,13 @@ func (c *Conn) readHandshake() (interface{}, error) { } // Write writes data to the connection. -func (c *Conn) Write(b []byte) (n int, err error) { - if err = c.Handshake(); err != nil { - return +func (c *Conn) Write(b []byte) (int, error) { + if c.err != nil { + return 0, c.err + } + + if c.err = c.Handshake(); c.err != nil { + return 0, c.err } c.out.Lock() @@ -737,10 +742,10 @@ func (c *Conn) Write(b []byte) (n int, err error) { if !c.handshakeComplete { return 0, alertInternalError } - if c.err != nil { - return 0, c.err - } - return c.writeRecord(recordTypeApplicationData, b) + + var n int + n, c.err = c.writeRecord(recordTypeApplicationData, b) + return n, c.err } // Read can be made to time out and return a net.Error with Timeout() == true diff --git a/src/pkg/crypto/x509/x509.go b/src/pkg/crypto/x509/x509.go index 7b45ba51f4..212662e21b 100644 --- a/src/pkg/crypto/x509/x509.go +++ b/src/pkg/crypto/x509/x509.go @@ -327,13 +327,9 @@ type Certificate struct { PolicyIdentifiers []asn1.ObjectIdentifier } -// UnsupportedAlgorithmError results from attempting to perform an operation -// that involves algorithms that are not currently implemented. -type UnsupportedAlgorithmError struct{} - -func (UnsupportedAlgorithmError) Error() string { - return "cannot verify signature: algorithm unimplemented" -} +// ErrUnsupportedAlgorithm results from attempting to perform an operation that +// involves algorithms that are not currently implemented. +var ErrUnsupportedAlgorithm = errors.New("crypto/x509: cannot verify signature: algorithm unimplemented") // ConstraintViolationError results when a requested usage is not permitted by // a certificate. For example: checking a signature when the public key isn't a @@ -341,7 +337,7 @@ func (UnsupportedAlgorithmError) Error() string { type ConstraintViolationError struct{} func (ConstraintViolationError) Error() string { - return "invalid signature: parent certificate cannot sign this kind of certificate" + return "crypto/x509: invalid signature: parent certificate cannot sign this kind of certificate" } func (c *Certificate) Equal(other *Certificate) bool { @@ -366,7 +362,7 @@ func (c *Certificate) CheckSignatureFrom(parent *Certificate) (err error) { } if parent.PublicKeyAlgorithm == UnknownPublicKeyAlgorithm { - return UnsupportedAlgorithmError{} + return ErrUnsupportedAlgorithm } // TODO(agl): don't ignore the path length constraint. @@ -389,12 +385,12 @@ func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature case SHA512WithRSA: hashType = crypto.SHA512 default: - return UnsupportedAlgorithmError{} + return ErrUnsupportedAlgorithm } h := hashType.New() if h == nil { - return UnsupportedAlgorithmError{} + return ErrUnsupportedAlgorithm } h.Write(signed) @@ -416,7 +412,7 @@ func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature } return } - return UnsupportedAlgorithmError{} + return ErrUnsupportedAlgorithm } // CheckCRLSignature checks that the signature in crl is from c. -- 2.50.0