aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/crypto
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-05-20 00:18:15 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-05-20 00:18:15 +0000
commit9ff56c9570642711d5b7ab29920ecf5dbff14a27 (patch)
treec891bdec1e6f073f73fedeef23718bc3ac30d499 /libgo/go/crypto
parent37cb25ed7acdb844b218231130e54b8b7a0ff6e6 (diff)
downloadgcc-9ff56c9570642711d5b7ab29920ecf5dbff14a27.zip
gcc-9ff56c9570642711d5b7ab29920ecf5dbff14a27.tar.gz
gcc-9ff56c9570642711d5b7ab29920ecf5dbff14a27.tar.bz2
Update to current version of Go library.
From-SVN: r173931
Diffstat (limited to 'libgo/go/crypto')
-rw-r--r--libgo/go/crypto/aes/const.go8
-rw-r--r--libgo/go/crypto/blowfish/cipher.go2
-rw-r--r--libgo/go/crypto/cast5/cast5.go2
-rw-r--r--libgo/go/crypto/cipher/cipher.go4
-rw-r--r--libgo/go/crypto/crypto.go2
-rw-r--r--libgo/go/crypto/elliptic/elliptic.go4
-rw-r--r--libgo/go/crypto/hmac/hmac.go4
-rw-r--r--libgo/go/crypto/md4/md4.go2
-rw-r--r--libgo/go/crypto/md5/md5.go2
-rw-r--r--libgo/go/crypto/ocsp/ocsp.go2
-rw-r--r--libgo/go/crypto/openpgp/armor/armor.go8
-rw-r--r--libgo/go/crypto/openpgp/armor/encode.go4
-rw-r--r--libgo/go/crypto/openpgp/error/error.go2
-rw-r--r--libgo/go/crypto/openpgp/keys.go63
-rw-r--r--libgo/go/crypto/openpgp/packet/packet.go2
-rw-r--r--libgo/go/crypto/openpgp/packet/private_key.go6
-rw-r--r--libgo/go/crypto/openpgp/packet/public_key.go3
-rw-r--r--libgo/go/crypto/openpgp/read.go2
-rw-r--r--libgo/go/crypto/openpgp/read_test.go51
-rw-r--r--libgo/go/crypto/openpgp/s2k/s2k.go2
-rw-r--r--libgo/go/crypto/rc4/rc4.go2
-rw-r--r--libgo/go/crypto/ripemd160/ripemd160.go2
-rw-r--r--libgo/go/crypto/rsa/pkcs1v15.go8
-rw-r--r--libgo/go/crypto/rsa/pkcs1v15_test.go16
-rw-r--r--libgo/go/crypto/rsa/rsa.go290
-rw-r--r--libgo/go/crypto/rsa/rsa_test.go36
-rw-r--r--libgo/go/crypto/sha1/sha1.go2
-rw-r--r--libgo/go/crypto/sha256/sha256.go3
-rw-r--r--libgo/go/crypto/sha512/sha512.go3
-rw-r--r--libgo/go/crypto/subtle/constant_time.go2
-rw-r--r--libgo/go/crypto/tls/ca_set.go89
-rw-r--r--libgo/go/crypto/tls/common.go19
-rw-r--r--libgo/go/crypto/tls/conn.go4
-rw-r--r--libgo/go/crypto/tls/handshake_client.go49
-rw-r--r--libgo/go/crypto/tls/handshake_messages.go10
-rw-r--r--libgo/go/crypto/tls/handshake_messages_test.go22
-rw-r--r--libgo/go/crypto/tls/handshake_server.go11
-rw-r--r--libgo/go/crypto/tls/handshake_server_test.go6
-rw-r--r--libgo/go/crypto/tls/tls.go3
-rw-r--r--libgo/go/crypto/twofish/twofish.go2
-rw-r--r--libgo/go/crypto/x509/cert_pool.go105
-rw-r--r--libgo/go/crypto/x509/verify.go239
-rw-r--r--libgo/go/crypto/x509/verify_test.go390
-rw-r--r--libgo/go/crypto/x509/x509.go153
-rw-r--r--libgo/go/crypto/x509/x509_test.go49
-rw-r--r--libgo/go/crypto/xtea/cipher.go4
46 files changed, 1224 insertions, 470 deletions
diff --git a/libgo/go/crypto/aes/const.go b/libgo/go/crypto/aes/const.go
index 97a5b64..25acd0d 100644
--- a/libgo/go/crypto/aes/const.go
+++ b/libgo/go/crypto/aes/const.go
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// AES constants - 8720 bytes of initialized data.
-
-// This package implements AES encryption (formerly Rijndael),
-// as defined in U.S. Federal Information Processing Standards Publication 197.
+// Package aes implements AES encryption (formerly Rijndael), as defined in
+// U.S. Federal Information Processing Standards Publication 197.
package aes
+// This file contains AES constants - 8720 bytes of initialized data.
+
// http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf
// AES is based on the mathematical behavior of binary polynomials
diff --git a/libgo/go/crypto/blowfish/cipher.go b/libgo/go/crypto/blowfish/cipher.go
index 947f762..f3c5175 100644
--- a/libgo/go/crypto/blowfish/cipher.go
+++ b/libgo/go/crypto/blowfish/cipher.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.
-// This package implements Bruce Schneier's Blowfish encryption algorithm.
+// Package blowfish implements Bruce Schneier's Blowfish encryption algorithm.
package blowfish
// The code is a port of Bruce Schneier's C implementation.
diff --git a/libgo/go/crypto/cast5/cast5.go b/libgo/go/crypto/cast5/cast5.go
index 35f3e64..cb62e31 100644
--- a/libgo/go/crypto/cast5/cast5.go
+++ b/libgo/go/crypto/cast5/cast5.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.
-// This package implements CAST5, as defined in RFC 2144. CAST5 is a common
+// Package cast5 implements CAST5, as defined in RFC 2144. CAST5 is a common
// OpenPGP cipher.
package cast5
diff --git a/libgo/go/crypto/cipher/cipher.go b/libgo/go/crypto/cipher/cipher.go
index 50516b2..1ffaa8c 100644
--- a/libgo/go/crypto/cipher/cipher.go
+++ b/libgo/go/crypto/cipher/cipher.go
@@ -2,8 +2,8 @@
// 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.
+// Package cipher 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
diff --git a/libgo/go/crypto/crypto.go b/libgo/go/crypto/crypto.go
index be6b34a..53672a4 100644
--- a/libgo/go/crypto/crypto.go
+++ b/libgo/go/crypto/crypto.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.
-// The crypto package collects common cryptographic constants.
+// Package crypto collects common cryptographic constants.
package crypto
import (
diff --git a/libgo/go/crypto/elliptic/elliptic.go b/libgo/go/crypto/elliptic/elliptic.go
index 2296e96..335c964 100644
--- a/libgo/go/crypto/elliptic/elliptic.go
+++ b/libgo/go/crypto/elliptic/elliptic.go
@@ -2,8 +2,8 @@
// 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 implements several standard elliptic curves over prime
+// fields.
package elliptic
// This package operates, internally, on Jacobian coordinates. For a given
diff --git a/libgo/go/crypto/hmac/hmac.go b/libgo/go/crypto/hmac/hmac.go
index 298fb2c..04ec86e 100644
--- a/libgo/go/crypto/hmac/hmac.go
+++ b/libgo/go/crypto/hmac/hmac.go
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// The hmac package implements the Keyed-Hash Message Authentication Code (HMAC)
-// as defined in U.S. Federal Information Processing Standards Publication 198.
+// Package hmac implements the Keyed-Hash Message Authentication Code (HMAC) as
+// defined in U.S. Federal Information Processing Standards Publication 198.
// An HMAC is a cryptographic hash that uses a key to sign a message.
// The receiver verifies the hash by recomputing it using the same key.
package hmac
diff --git a/libgo/go/crypto/md4/md4.go b/libgo/go/crypto/md4/md4.go
index ee46544..848d955 100644
--- a/libgo/go/crypto/md4/md4.go
+++ b/libgo/go/crypto/md4/md4.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.
-// This package implements the MD4 hash algorithm as defined in RFC 1320.
+// Package md4 implements the MD4 hash algorithm as defined in RFC 1320.
package md4
import (
diff --git a/libgo/go/crypto/md5/md5.go b/libgo/go/crypto/md5/md5.go
index 8f93fc4..378faa6 100644
--- a/libgo/go/crypto/md5/md5.go
+++ b/libgo/go/crypto/md5/md5.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.
-// This package implements the MD5 hash algorithm as defined in RFC 1321.
+// Package md5 implements the MD5 hash algorithm as defined in RFC 1321.
package md5
import (
diff --git a/libgo/go/crypto/ocsp/ocsp.go b/libgo/go/crypto/ocsp/ocsp.go
index f42d808..acd75b8 100644
--- a/libgo/go/crypto/ocsp/ocsp.go
+++ b/libgo/go/crypto/ocsp/ocsp.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.
-// This package parses OCSP responses as specified in RFC 2560. OCSP responses
+// Package ocsp parses OCSP responses as specified in RFC 2560. OCSP responses
// are signed messages attesting to the validity of a certificate for a small
// period of time. This is used to manage revocation for X.509 certificates.
package ocsp
diff --git a/libgo/go/crypto/openpgp/armor/armor.go b/libgo/go/crypto/openpgp/armor/armor.go
index 0c5ae9d..8da612c 100644
--- a/libgo/go/crypto/openpgp/armor/armor.go
+++ b/libgo/go/crypto/openpgp/armor/armor.go
@@ -2,15 +2,15 @@
// 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
+// Package armor 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 (
+ "bufio"
"bytes"
"crypto/openpgp/error"
"encoding/base64"
- "encoding/line"
"io"
"os"
)
@@ -63,7 +63,7 @@ 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
+ in *bufio.Reader
buf []byte
eof bool
crc uint32
@@ -156,7 +156,7 @@ func (r *openpgpReader) Read(p []byte) (n int, err os.Error) {
// 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)
+ r, _ := bufio.NewReaderSize(in, 100)
var line []byte
ignoreNext := false
diff --git a/libgo/go/crypto/openpgp/armor/encode.go b/libgo/go/crypto/openpgp/armor/encode.go
index 0f7de02..99dee37 100644
--- a/libgo/go/crypto/openpgp/armor/encode.go
+++ b/libgo/go/crypto/openpgp/armor/encode.go
@@ -18,9 +18,9 @@ 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)
+ _, err = out.Write(s)
if err != nil {
- return
+ return err
}
}
return
diff --git a/libgo/go/crypto/openpgp/error/error.go b/libgo/go/crypto/openpgp/error/error.go
index 053d159..3759ce1 100644
--- a/libgo/go/crypto/openpgp/error/error.go
+++ b/libgo/go/crypto/openpgp/error/error.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.
-// This package contains common error types for the OpenPGP packages.
+// Package error contains common error types for the OpenPGP packages.
package error
import (
diff --git a/libgo/go/crypto/openpgp/keys.go b/libgo/go/crypto/openpgp/keys.go
index ecaa86f..6c03f88 100644
--- a/libgo/go/crypto/openpgp/keys.go
+++ b/libgo/go/crypto/openpgp/keys.go
@@ -5,6 +5,7 @@
package openpgp
import (
+ "crypto/openpgp/armor"
"crypto/openpgp/error"
"crypto/openpgp/packet"
"io"
@@ -13,6 +14,8 @@ import (
// PublicKeyType is the armor type for a PGP public key.
var PublicKeyType = "PGP PUBLIC KEY BLOCK"
+// PrivateKeyType is the armor type for a PGP private key.
+var PrivateKeyType = "PGP PRIVATE KEY BLOCK"
// An Entity represents the components of an OpenPGP key: a primary public key
// (which must be a signing key), one or more identities claimed by that key,
@@ -101,37 +104,50 @@ func (el EntityList) DecryptionKeys() (keys []Key) {
// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file.
func ReadArmoredKeyRing(r io.Reader) (EntityList, os.Error) {
- body, err := readArmored(r, PublicKeyType)
+ block, err := armor.Decode(r)
+ if err == os.EOF {
+ return nil, error.InvalidArgumentError("no armored data found")
+ }
if err != nil {
return nil, err
}
+ if block.Type != PublicKeyType && block.Type != PrivateKeyType {
+ return nil, error.InvalidArgumentError("expected public or private key block, got: " + block.Type)
+ }
- return ReadKeyRing(body)
+ return ReadKeyRing(block.Body)
}
-// ReadKeyRing reads one or more public/private keys, ignoring unsupported keys.
+// ReadKeyRing reads one or more public/private keys. Unsupported keys are
+// ignored as long as at least a single valid key is found.
func ReadKeyRing(r io.Reader) (el EntityList, err os.Error) {
packets := packet.NewReader(r)
+ var lastUnsupportedError os.Error
for {
var e *Entity
e, err = readEntity(packets)
if err != nil {
if _, ok := err.(error.UnsupportedError); ok {
+ lastUnsupportedError = err
err = readToNextPublicKey(packets)
}
if err == os.EOF {
err = nil
- return
+ break
}
if err != nil {
el = nil
- return
+ break
}
} else {
el = append(el, e)
}
}
+
+ if len(el) == 0 && err == nil {
+ err = lastUnsupportedError
+ }
return
}
@@ -197,25 +213,28 @@ EachPacket:
current.Name = pkt.Id
current.UserId = pkt
e.Identities[pkt.Id] = current
- p, err = packets.Next()
- if err == os.EOF {
- err = io.ErrUnexpectedEOF
- }
- if err != nil {
- if _, ok := err.(error.UnsupportedError); ok {
+
+ for {
+ p, err = packets.Next()
+ if err == os.EOF {
+ return nil, io.ErrUnexpectedEOF
+ } else if err != nil {
return nil, err
}
- return nil, error.StructuralError("identity self-signature invalid: " + err.String())
- }
- current.SelfSignature, ok = p.(*packet.Signature)
- if !ok {
- return nil, error.StructuralError("user ID packet not followed by self signature")
- }
- if current.SelfSignature.SigType != packet.SigTypePositiveCert {
- return nil, error.StructuralError("user ID self-signature with wrong type")
- }
- if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, current.SelfSignature); err != nil {
- return nil, error.StructuralError("user ID self-signature invalid: " + err.String())
+
+ sig, ok := p.(*packet.Signature)
+ if !ok {
+ return nil, error.StructuralError("user ID packet not followed by self-signature")
+ }
+
+ if sig.SigType == packet.SigTypePositiveCert && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId {
+ if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, sig); err != nil {
+ return nil, error.StructuralError("user ID self-signature invalid: " + err.String())
+ }
+ current.SelfSignature = sig
+ break
+ }
+ current.Signatures = append(current.Signatures, sig)
}
case *packet.Signature:
if current == nil {
diff --git a/libgo/go/crypto/openpgp/packet/packet.go b/libgo/go/crypto/openpgp/packet/packet.go
index 57ff3af..c0ec44d 100644
--- a/libgo/go/crypto/openpgp/packet/packet.go
+++ b/libgo/go/crypto/openpgp/packet/packet.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.
-// This package implements parsing and serialisation of OpenPGP packets, as
+// Package packet implements parsing and serialisation of OpenPGP packets, as
// specified in RFC 4880.
package packet
diff --git a/libgo/go/crypto/openpgp/packet/private_key.go b/libgo/go/crypto/openpgp/packet/private_key.go
index 6944823..fde2a99 100644
--- a/libgo/go/crypto/openpgp/packet/private_key.go
+++ b/libgo/go/crypto/openpgp/packet/private_key.go
@@ -164,8 +164,10 @@ func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err os.Error) {
}
rsaPriv.D = new(big.Int).SetBytes(d)
- rsaPriv.P = new(big.Int).SetBytes(p)
- rsaPriv.Q = new(big.Int).SetBytes(q)
+ rsaPriv.Primes = make([]*big.Int, 2)
+ rsaPriv.Primes[0] = new(big.Int).SetBytes(p)
+ rsaPriv.Primes[1] = new(big.Int).SetBytes(q)
+ rsaPriv.Precompute()
pk.PrivateKey = rsaPriv
pk.Encrypted = false
pk.encryptedData = nil
diff --git a/libgo/go/crypto/openpgp/packet/public_key.go b/libgo/go/crypto/openpgp/packet/public_key.go
index ebef481..cd4a9ae 100644
--- a/libgo/go/crypto/openpgp/packet/public_key.go
+++ b/libgo/go/crypto/openpgp/packet/public_key.go
@@ -15,6 +15,7 @@ import (
"hash"
"io"
"os"
+ "strconv"
)
// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2.
@@ -47,7 +48,7 @@ func (pk *PublicKey) parse(r io.Reader) (err os.Error) {
case PubKeyAlgoDSA:
err = pk.parseDSA(r)
default:
- err = error.UnsupportedError("public key type")
+ err = error.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
}
if err != nil {
return
diff --git a/libgo/go/crypto/openpgp/read.go b/libgo/go/crypto/openpgp/read.go
index ac6998f..4f84dff 100644
--- a/libgo/go/crypto/openpgp/read.go
+++ b/libgo/go/crypto/openpgp/read.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.
-// This openpgp package implements high level operations on OpenPGP messages.
+// Package openpgp implements high level operations on OpenPGP messages.
package openpgp
import (
diff --git a/libgo/go/crypto/openpgp/read_test.go b/libgo/go/crypto/openpgp/read_test.go
index 6218d99..423c85b 100644
--- a/libgo/go/crypto/openpgp/read_test.go
+++ b/libgo/go/crypto/openpgp/read_test.go
@@ -230,6 +230,23 @@ func TestDetachedSignatureDSA(t *testing.T) {
testDetachedSignature(t, kring, readerFromHex(detachedSignatureDSAHex), signedInput, "binary", testKey3KeyId)
}
+func TestReadingArmoredPrivateKey(t *testing.T) {
+ el, err := ReadArmoredKeyRing(bytes.NewBufferString(armoredPrivateKeyBlock))
+ if err != nil {
+ t.Error(err)
+ }
+ if len(el) != 1 {
+ t.Errorf("got %d entities, wanted 1\n", len(el))
+ }
+}
+
+func TestNoArmoredData(t *testing.T) {
+ _, err := ReadArmoredKeyRing(bytes.NewBufferString("foo"))
+ if _, ok := err.(error.InvalidArgumentError); !ok {
+ t.Errorf("error was not an InvalidArgumentError: %s", err)
+ }
+}
+
const testKey1KeyId = 0xA34D7E18C20C31BB
const testKey3KeyId = 0x338934250CCC0360
@@ -259,3 +276,37 @@ const symmetricallyEncryptedCompressedHex = "8c0d04030302eb4a03808145d0d260c92f7
const dsaTestKeyHex = "9901a2044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794"
const dsaTestKeyPrivateHex = "9501bb044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4d00009f592e0619d823953577d4503061706843317e4fee083db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794"
+
+const armoredPrivateKeyBlock = `-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v1.4.10 (GNU/Linux)
+
+lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp
+idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn
+vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB
+AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X
+0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL
+IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk
+VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn
+gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9
+TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx
+q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz
+dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA
+CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1
+ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+
+eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid
+AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV
+bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK
+/UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA
+A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX
+TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc
+lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6
+rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN
+oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8
+QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU
+nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC
+AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp
+BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad
+AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL
+VrM0m72/jnpKo04=
+=zNCn
+-----END PGP PRIVATE KEY BLOCK-----`
diff --git a/libgo/go/crypto/openpgp/s2k/s2k.go b/libgo/go/crypto/openpgp/s2k/s2k.go
index 873b33d..93b7582 100644
--- a/libgo/go/crypto/openpgp/s2k/s2k.go
+++ b/libgo/go/crypto/openpgp/s2k/s2k.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.
-// This package implements the various OpenPGP string-to-key transforms as
+// Package s2k implements the various OpenPGP string-to-key transforms as
// specified in RFC 4800 section 3.7.1.
package s2k
diff --git a/libgo/go/crypto/rc4/rc4.go b/libgo/go/crypto/rc4/rc4.go
index 65fd195..7ee4710 100644
--- a/libgo/go/crypto/rc4/rc4.go
+++ b/libgo/go/crypto/rc4/rc4.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.
-// This package implements RC4 encryption, as defined in Bruce Schneier's
+// Package rc4 implements RC4 encryption, as defined in Bruce Schneier's
// Applied Cryptography.
package rc4
diff --git a/libgo/go/crypto/ripemd160/ripemd160.go b/libgo/go/crypto/ripemd160/ripemd160.go
index 6e88521..5aaca59 100644
--- a/libgo/go/crypto/ripemd160/ripemd160.go
+++ b/libgo/go/crypto/ripemd160/ripemd160.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.
-// This package implements the RIPEMD-160 hash algorithm.
+// Package ripemd160 implements the RIPEMD-160 hash algorithm.
package ripemd160
// RIPEMD-160 is designed by by Hans Dobbertin, Antoon Bosselaers, and Bart
diff --git a/libgo/go/crypto/rsa/pkcs1v15.go b/libgo/go/crypto/rsa/pkcs1v15.go
index 9a71841..3defa62 100644
--- a/libgo/go/crypto/rsa/pkcs1v15.go
+++ b/libgo/go/crypto/rsa/pkcs1v15.go
@@ -149,10 +149,10 @@ func nonZeroRandomBytes(s []byte, rand io.Reader) (err os.Error) {
// precompute a prefix of the digest value that makes a valid ASN1 DER string
// with the correct contents.
var hashPrefixes = map[crypto.Hash][]byte{
- crypto.MD5: []byte{0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10},
- crypto.SHA1: []byte{0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14},
- crypto.SHA256: []byte{0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
- crypto.SHA384: []byte{0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
+ crypto.MD5: {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10},
+ crypto.SHA1: {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14},
+ crypto.SHA256: {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
+ crypto.SHA384: {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
crypto.SHA512: {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40},
crypto.MD5SHA1: {}, // A special TLS case which doesn't use an ASN1 prefix.
crypto.RIPEMD160: {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31, 0x04, 0x14},
diff --git a/libgo/go/crypto/rsa/pkcs1v15_test.go b/libgo/go/crypto/rsa/pkcs1v15_test.go
index 30a4824..d69bacf 100644
--- a/libgo/go/crypto/rsa/pkcs1v15_test.go
+++ b/libgo/go/crypto/rsa/pkcs1v15_test.go
@@ -197,12 +197,6 @@ func TestVerifyPKCS1v15(t *testing.T) {
}
}
-func bigFromString(s string) *big.Int {
- ret := new(big.Int)
- ret.SetString(s, 10)
- return ret
-}
-
// In order to generate new test vectors you'll need the PEM form of this key:
// -----BEGIN RSA PRIVATE KEY-----
// MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0
@@ -216,10 +210,12 @@ func bigFromString(s string) *big.Int {
var rsaPrivateKey = &PrivateKey{
PublicKey: PublicKey{
- N: bigFromString("9353930466774385905609975137998169297361893554149986716853295022578535724979677252958524466350471210367835187480748268864277464700638583474144061408845077"),
+ N: fromBase10("9353930466774385905609975137998169297361893554149986716853295022578535724979677252958524466350471210367835187480748268864277464700638583474144061408845077"),
E: 65537,
},
- D: bigFromString("7266398431328116344057699379749222532279343923819063639497049039389899328538543087657733766554155839834519529439851673014800261285757759040931985506583861"),
- P: bigFromString("98920366548084643601728869055592650835572950932266967461790948584315647051443"),
- Q: bigFromString("94560208308847015747498523884063394671606671904944666360068158221458669711639"),
+ D: fromBase10("7266398431328116344057699379749222532279343923819063639497049039389899328538543087657733766554155839834519529439851673014800261285757759040931985506583861"),
+ Primes: []*big.Int{
+ fromBase10("98920366548084643601728869055592650835572950932266967461790948584315647051443"),
+ fromBase10("94560208308847015747498523884063394671606671904944666360068158221458669711639"),
+ },
}
diff --git a/libgo/go/crypto/rsa/rsa.go b/libgo/go/crypto/rsa/rsa.go
index b3b212c..e1813db 100644
--- a/libgo/go/crypto/rsa/rsa.go
+++ b/libgo/go/crypto/rsa/rsa.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.
-// This package implements RSA encryption as specified in PKCS#1.
+// Package rsa implements RSA encryption as specified in PKCS#1.
package rsa
// TODO(agl): Add support for PSS padding.
@@ -13,7 +13,6 @@ import (
"hash"
"io"
"os"
- "sync"
)
var bigZero = big.NewInt(0)
@@ -90,50 +89,60 @@ type PublicKey struct {
// A PrivateKey represents an RSA key
type PrivateKey struct {
- PublicKey // public part.
- D *big.Int // private exponent
- P, Q, R *big.Int // prime factors of N (R may be nil)
-
- rwMutex sync.RWMutex // protects the following
- dP, dQ, dR *big.Int // D mod (P-1) (or mod Q-1 etc)
- qInv *big.Int // q^-1 mod p
- pq *big.Int // P*Q
- tr *big.Int // pq·tr ≡ 1 mod r
+ PublicKey // public part.
+ D *big.Int // private exponent
+ Primes []*big.Int // prime factors of N, has >= 2 elements.
+
+ // Precomputed contains precomputed values that speed up private
+ // operations, if availible.
+ Precomputed PrecomputedValues
+}
+
+type PrecomputedValues struct {
+ Dp, Dq *big.Int // D mod (P-1) (or mod Q-1)
+ Qinv *big.Int // Q^-1 mod Q
+
+ // CRTValues is used for the 3rd and subsequent primes. Due to a
+ // historical accident, the CRT for the first two primes is handled
+ // differently in PKCS#1 and interoperability is sufficiently
+ // important that we mirror this.
+ CRTValues []CRTValue
+}
+
+// CRTValue contains the precomputed chinese remainder theorem values.
+type CRTValue struct {
+ Exp *big.Int // D mod (prime-1).
+ Coeff *big.Int // R·Coeff ≡ 1 mod Prime.
+ R *big.Int // product of primes prior to this (inc p and q).
}
// Validate performs basic sanity checks on the key.
// It returns nil if the key is valid, or else an os.Error describing a problem.
func (priv *PrivateKey) Validate() os.Error {
- // Check that p, q and, maybe, r are prime. Note that this is just a
- // sanity check. Since the random witnesses chosen by ProbablyPrime are
- // deterministic, given the candidate number, it's easy for an attack
- // to generate composites that pass this test.
- if !big.ProbablyPrime(priv.P, 20) {
- return os.ErrorString("P is composite")
- }
- if !big.ProbablyPrime(priv.Q, 20) {
- return os.ErrorString("Q is composite")
- }
- if priv.R != nil && !big.ProbablyPrime(priv.R, 20) {
- return os.ErrorString("R is composite")
+ // Check that the prime factors are actually prime. Note that this is
+ // just a sanity check. Since the random witnesses chosen by
+ // ProbablyPrime are deterministic, given the candidate number, it's
+ // easy for an attack to generate composites that pass this test.
+ for _, prime := range priv.Primes {
+ if !big.ProbablyPrime(prime, 20) {
+ return os.ErrorString("Prime factor is composite")
+ }
}
- // Check that p*q*r == n.
- modulus := new(big.Int).Mul(priv.P, priv.Q)
- if priv.R != nil {
- modulus.Mul(modulus, priv.R)
+ // Check that Πprimes == n.
+ modulus := new(big.Int).Set(bigOne)
+ for _, prime := range priv.Primes {
+ modulus.Mul(modulus, prime)
}
if modulus.Cmp(priv.N) != 0 {
return os.ErrorString("invalid modulus")
}
- // Check that e and totient(p, q, r) are coprime.
- pminus1 := new(big.Int).Sub(priv.P, bigOne)
- qminus1 := new(big.Int).Sub(priv.Q, bigOne)
- totient := new(big.Int).Mul(pminus1, qminus1)
- if priv.R != nil {
- rminus1 := new(big.Int).Sub(priv.R, bigOne)
- totient.Mul(totient, rminus1)
+ // Check that e and totient(Πprimes) are coprime.
+ totient := new(big.Int).Set(bigOne)
+ for _, prime := range priv.Primes {
+ pminus1 := new(big.Int).Sub(prime, bigOne)
+ totient.Mul(totient, pminus1)
}
e := big.NewInt(int64(priv.E))
gcd := new(big.Int)
@@ -143,7 +152,7 @@ func (priv *PrivateKey) Validate() os.Error {
if gcd.Cmp(bigOne) != 0 {
return os.ErrorString("invalid public exponent E")
}
- // Check that de ≡ 1 (mod totient(p, q, r))
+ // Check that de ≡ 1 (mod totient(Πprimes))
de := new(big.Int).Mul(priv.D, e)
de.Mod(de, totient)
if de.Cmp(bigOne) != 0 {
@@ -154,6 +163,20 @@ func (priv *PrivateKey) Validate() os.Error {
// GenerateKey generates an RSA keypair of the given bit size.
func GenerateKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) {
+ return GenerateMultiPrimeKey(rand, 2, bits)
+}
+
+// GenerateMultiPrimeKey generates a multi-prime RSA keypair of the given bit
+// size, as suggested in [1]. Although the public keys are compatible
+// (actually, indistinguishable) from the 2-prime case, the private keys are
+// not. Thus it may not be possible to export multi-prime private keys in
+// certain formats or to subsequently import them into other code.
+//
+// Table 1 in [2] suggests maximum numbers of primes for a given size.
+//
+// [1] US patent 4405829 (1972, expired)
+// [2] http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf
+func GenerateMultiPrimeKey(rand io.Reader, nprimes int, bits int) (priv *PrivateKey, err os.Error) {
priv = new(PrivateKey)
// Smaller public exponents lead to faster public key
// operations. Since the exponent must be coprime to
@@ -165,100 +188,41 @@ func GenerateKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) {
// [1] http://marc.info/?l=cryptography&m=115694833312008&w=2
priv.E = 3
- pminus1 := new(big.Int)
- qminus1 := new(big.Int)
- totient := new(big.Int)
-
- for {
- p, err := randomPrime(rand, bits/2)
- if err != nil {
- return nil, err
- }
-
- q, err := randomPrime(rand, bits/2)
- if err != nil {
- return nil, err
- }
-
- if p.Cmp(q) == 0 {
- continue
- }
-
- n := new(big.Int).Mul(p, q)
- pminus1.Sub(p, bigOne)
- qminus1.Sub(q, bigOne)
- totient.Mul(pminus1, qminus1)
-
- g := new(big.Int)
- priv.D = new(big.Int)
- y := new(big.Int)
- e := big.NewInt(int64(priv.E))
- big.GcdInt(g, priv.D, y, e, totient)
-
- if g.Cmp(bigOne) == 0 {
- priv.D.Add(priv.D, totient)
- priv.P = p
- priv.Q = q
- priv.N = n
-
- break
- }
+ if nprimes < 2 {
+ return nil, os.ErrorString("rsa.GenerateMultiPrimeKey: nprimes must be >= 2")
}
- return
-}
-
-// Generate3PrimeKey generates a 3-prime RSA keypair of the given bit size, as
-// suggested in [1]. Although the public keys are compatible (actually,
-// indistinguishable) from the 2-prime case, the private keys are not. Thus it
-// may not be possible to export 3-prime private keys in certain formats or to
-// subsequently import them into other code.
-//
-// Table 1 in [2] suggests that size should be >= 1024 when using 3 primes.
-//
-// [1] US patent 4405829 (1972, expired)
-// [2] http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf
-func Generate3PrimeKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) {
- priv = new(PrivateKey)
- priv.E = 3
-
- pminus1 := new(big.Int)
- qminus1 := new(big.Int)
- rminus1 := new(big.Int)
- totient := new(big.Int)
+ primes := make([]*big.Int, nprimes)
+NextSetOfPrimes:
for {
- p, err := randomPrime(rand, bits/3)
- if err != nil {
- return nil, err
- }
-
- todo := bits - p.BitLen()
- q, err := randomPrime(rand, todo/2)
- if err != nil {
- return nil, err
+ todo := bits
+ for i := 0; i < nprimes; i++ {
+ primes[i], err = randomPrime(rand, todo/(nprimes-i))
+ if err != nil {
+ return nil, err
+ }
+ todo -= primes[i].BitLen()
}
- todo -= q.BitLen()
- r, err := randomPrime(rand, todo)
- if err != nil {
- return nil, err
+ // Make sure that primes is pairwise unequal.
+ for i, prime := range primes {
+ for j := 0; j < i; j++ {
+ if prime.Cmp(primes[j]) == 0 {
+ continue NextSetOfPrimes
+ }
+ }
}
- if p.Cmp(q) == 0 ||
- q.Cmp(r) == 0 ||
- r.Cmp(p) == 0 {
- continue
+ n := new(big.Int).Set(bigOne)
+ totient := new(big.Int).Set(bigOne)
+ pminus1 := new(big.Int)
+ for _, prime := range primes {
+ n.Mul(n, prime)
+ pminus1.Sub(prime, bigOne)
+ totient.Mul(totient, pminus1)
}
- n := new(big.Int).Mul(p, q)
- n.Mul(n, r)
- pminus1.Sub(p, bigOne)
- qminus1.Sub(q, bigOne)
- rminus1.Sub(r, bigOne)
- totient.Mul(pminus1, qminus1)
- totient.Mul(totient, rminus1)
-
g := new(big.Int)
priv.D = new(big.Int)
y := new(big.Int)
@@ -267,15 +231,14 @@ func Generate3PrimeKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error
if g.Cmp(bigOne) == 0 {
priv.D.Add(priv.D, totient)
- priv.P = p
- priv.Q = q
- priv.R = r
+ priv.Primes = primes
priv.N = n
break
}
}
+ priv.Precompute()
return
}
@@ -409,23 +372,34 @@ func modInverse(a, n *big.Int) (ia *big.Int, ok bool) {
return x, true
}
-// precompute performs some calculations that speed up private key operations
+// Precompute performs some calculations that speed up private key operations
// in the future.
-func (priv *PrivateKey) precompute() {
- priv.dP = new(big.Int).Sub(priv.P, bigOne)
- priv.dP.Mod(priv.D, priv.dP)
+func (priv *PrivateKey) Precompute() {
+ if priv.Precomputed.Dp != nil {
+ return
+ }
- priv.dQ = new(big.Int).Sub(priv.Q, bigOne)
- priv.dQ.Mod(priv.D, priv.dQ)
+ priv.Precomputed.Dp = new(big.Int).Sub(priv.Primes[0], bigOne)
+ priv.Precomputed.Dp.Mod(priv.D, priv.Precomputed.Dp)
- priv.qInv = new(big.Int).ModInverse(priv.Q, priv.P)
+ priv.Precomputed.Dq = new(big.Int).Sub(priv.Primes[1], bigOne)
+ priv.Precomputed.Dq.Mod(priv.D, priv.Precomputed.Dq)
- if priv.R != nil {
- priv.dR = new(big.Int).Sub(priv.R, bigOne)
- priv.dR.Mod(priv.D, priv.dR)
+ priv.Precomputed.Qinv = new(big.Int).ModInverse(priv.Primes[1], priv.Primes[0])
- priv.pq = new(big.Int).Mul(priv.P, priv.Q)
- priv.tr = new(big.Int).ModInverse(priv.pq, priv.R)
+ r := new(big.Int).Mul(priv.Primes[0], priv.Primes[1])
+ priv.Precomputed.CRTValues = make([]CRTValue, len(priv.Primes)-2)
+ for i := 2; i < len(priv.Primes); i++ {
+ prime := priv.Primes[i]
+ values := &priv.Precomputed.CRTValues[i-2]
+
+ values.Exp = new(big.Int).Sub(prime, bigOne)
+ values.Exp.Mod(priv.D, values.Exp)
+
+ values.R = new(big.Int).Set(r)
+ values.Coeff = new(big.Int).ModInverse(r, prime)
+
+ r.Mul(r, prime)
}
}
@@ -463,53 +437,41 @@ func decrypt(rand io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err os.E
}
bigE := big.NewInt(int64(priv.E))
rpowe := new(big.Int).Exp(r, bigE, priv.N)
- c.Mul(c, rpowe)
- c.Mod(c, priv.N)
- }
-
- priv.rwMutex.RLock()
-
- if priv.dP == nil && priv.P != nil {
- priv.rwMutex.RUnlock()
- priv.rwMutex.Lock()
- if priv.dP == nil && priv.P != nil {
- priv.precompute()
- }
- priv.rwMutex.Unlock()
- priv.rwMutex.RLock()
+ cCopy := new(big.Int).Set(c)
+ cCopy.Mul(cCopy, rpowe)
+ cCopy.Mod(cCopy, priv.N)
+ c = cCopy
}
- if priv.dP == nil {
+ if priv.Precomputed.Dp == nil {
m = new(big.Int).Exp(c, priv.D, priv.N)
} else {
// We have the precalculated values needed for the CRT.
- m = new(big.Int).Exp(c, priv.dP, priv.P)
- m2 := new(big.Int).Exp(c, priv.dQ, priv.Q)
+ m = new(big.Int).Exp(c, priv.Precomputed.Dp, priv.Primes[0])
+ m2 := new(big.Int).Exp(c, priv.Precomputed.Dq, priv.Primes[1])
m.Sub(m, m2)
if m.Sign() < 0 {
- m.Add(m, priv.P)
+ m.Add(m, priv.Primes[0])
}
- m.Mul(m, priv.qInv)
- m.Mod(m, priv.P)
- m.Mul(m, priv.Q)
+ m.Mul(m, priv.Precomputed.Qinv)
+ m.Mod(m, priv.Primes[0])
+ m.Mul(m, priv.Primes[1])
m.Add(m, m2)
- if priv.dR != nil {
- // 3-prime CRT.
- m2.Exp(c, priv.dR, priv.R)
+ for i, values := range priv.Precomputed.CRTValues {
+ prime := priv.Primes[2+i]
+ m2.Exp(c, values.Exp, prime)
m2.Sub(m2, m)
- m2.Mul(m2, priv.tr)
- m2.Mod(m2, priv.R)
+ m2.Mul(m2, values.Coeff)
+ m2.Mod(m2, prime)
if m2.Sign() < 0 {
- m2.Add(m2, priv.R)
+ m2.Add(m2, prime)
}
- m2.Mul(m2, priv.pq)
+ m2.Mul(m2, values.R)
m.Add(m, m2)
}
}
- priv.rwMutex.RUnlock()
-
if ir != nil {
// Unblind.
m.Mul(m, ir)
diff --git a/libgo/go/crypto/rsa/rsa_test.go b/libgo/go/crypto/rsa/rsa_test.go
index d8a936e..c36bca1 100644
--- a/libgo/go/crypto/rsa/rsa_test.go
+++ b/libgo/go/crypto/rsa/rsa_test.go
@@ -30,7 +30,20 @@ func Test3PrimeKeyGeneration(t *testing.T) {
}
size := 768
- priv, err := Generate3PrimeKey(rand.Reader, size)
+ priv, err := GenerateMultiPrimeKey(rand.Reader, 3, size)
+ if err != nil {
+ t.Errorf("failed to generate key")
+ }
+ testKeyBasics(t, priv)
+}
+
+func Test4PrimeKeyGeneration(t *testing.T) {
+ if testing.Short() {
+ return
+ }
+
+ size := 768
+ priv, err := GenerateMultiPrimeKey(rand.Reader, 4, size)
if err != nil {
t.Errorf("failed to generate key")
}
@@ -45,6 +58,7 @@ func testKeyBasics(t *testing.T, priv *PrivateKey) {
pub := &priv.PublicKey
m := big.NewInt(42)
c := encrypt(new(big.Int), pub, m)
+
m2, err := decrypt(nil, priv, c)
if err != nil {
t.Errorf("error while decrypting: %s", err)
@@ -59,7 +73,7 @@ func testKeyBasics(t *testing.T, priv *PrivateKey) {
t.Errorf("error while decrypting (blind): %s", err)
}
if m.Cmp(m3) != 0 {
- t.Errorf("(blind) got:%v, want:%v", m3, m)
+ t.Errorf("(blind) got:%v, want:%v (%#v)", m3, m, priv)
}
}
@@ -77,10 +91,12 @@ func BenchmarkRSA2048Decrypt(b *testing.B) {
E: 3,
},
D: fromBase10("9542755287494004433998723259516013739278699355114572217325597900889416163458809501304132487555642811888150937392013824621448709836142886006653296025093941418628992648429798282127303704957273845127141852309016655778568546006839666463451542076964744073572349705538631742281931858219480985907271975884773482372966847639853897890615456605598071088189838676728836833012254065983259638538107719766738032720239892094196108713378822882383694456030043492571063441943847195939549773271694647657549658603365629458610273821292232646334717612674519997533901052790334279661754176490593041941863932308687197618671528035670452762731"),
- P: fromBase10("130903255182996722426771613606077755295583329135067340152947172868415809027537376306193179624298874215608270802054347609836776473930072411958753044562214537013874103802006369634761074377213995983876788718033850153719421695468704276694983032644416930879093914927146648402139231293035971427838068945045019075433"),
- Q: fromBase10("109348945610485453577574767652527472924289229538286649661240938988020367005475727988253438647560958573506159449538793540472829815903949343191091817779240101054552748665267574271163617694640513549693841337820602726596756351006149518830932261246698766355347898158548465400674856021497190430791824869615170301029"),
+ Primes: []*big.Int{
+ fromBase10("130903255182996722426771613606077755295583329135067340152947172868415809027537376306193179624298874215608270802054347609836776473930072411958753044562214537013874103802006369634761074377213995983876788718033850153719421695468704276694983032644416930879093914927146648402139231293035971427838068945045019075433"),
+ fromBase10("109348945610485453577574767652527472924289229538286649661240938988020367005475727988253438647560958573506159449538793540472829815903949343191091817779240101054552748665267574271163617694640513549693841337820602726596756351006149518830932261246698766355347898158548465400674856021497190430791824869615170301029"),
+ },
}
- priv.precompute()
+ priv.Precompute()
c := fromBase10("1000")
@@ -99,11 +115,13 @@ func Benchmark3PrimeRSA2048Decrypt(b *testing.B) {
E: 3,
},
D: fromBase10("10897585948254795600358846499957366070880176878341177571733155050184921896034527397712889205732614568234385175145686545381899460748279607074689061600935843283397424506622998458510302603922766336783617368686090042765718290914099334449154829375179958369993407724946186243249568928237086215759259909861748642124071874879861299389874230489928271621259294894142840428407196932444474088857746123104978617098858619445675532587787023228852383149557470077802718705420275739737958953794088728369933811184572620857678792001136676902250566845618813972833750098806496641114644760255910789397593428910198080271317419213080834885003"),
- P: fromBase10("1025363189502892836833747188838978207017355117492483312747347695538428729137306368764177201532277413433182799108299960196606011786562992097313508180436744488171474690412562218914213688661311117337381958560443"),
- Q: fromBase10("3467903426626310123395340254094941045497208049900750380025518552334536945536837294961497712862519984786362199788654739924501424784631315081391467293694361474867825728031147665777546570788493758372218019373"),
- R: fromBase10("4597024781409332673052708605078359346966325141767460991205742124888960305710298765592730135879076084498363772408626791576005136245060321874472727132746643162385746062759369754202494417496879741537284589047"),
+ Primes: []*big.Int{
+ fromBase10("1025363189502892836833747188838978207017355117492483312747347695538428729137306368764177201532277413433182799108299960196606011786562992097313508180436744488171474690412562218914213688661311117337381958560443"),
+ fromBase10("3467903426626310123395340254094941045497208049900750380025518552334536945536837294961497712862519984786362199788654739924501424784631315081391467293694361474867825728031147665777546570788493758372218019373"),
+ fromBase10("4597024781409332673052708605078359346966325141767460991205742124888960305710298765592730135879076084498363772408626791576005136245060321874472727132746643162385746062759369754202494417496879741537284589047"),
+ },
}
- priv.precompute()
+ priv.Precompute()
c := fromBase10("1000")
diff --git a/libgo/go/crypto/sha1/sha1.go b/libgo/go/crypto/sha1/sha1.go
index e6aa096..788d1ff 100644
--- a/libgo/go/crypto/sha1/sha1.go
+++ b/libgo/go/crypto/sha1/sha1.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.
-// This package implements the SHA1 hash algorithm as defined in RFC 3174.
+// Package sha1 implements the SHA1 hash algorithm as defined in RFC 3174.
package sha1
import (
diff --git a/libgo/go/crypto/sha256/sha256.go b/libgo/go/crypto/sha256/sha256.go
index 69b356b..a2c058d 100644
--- a/libgo/go/crypto/sha256/sha256.go
+++ b/libgo/go/crypto/sha256/sha256.go
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// This package implements the SHA224 and SHA256 hash algorithms as defined in FIPS 180-2.
+// Package sha256 implements the SHA224 and SHA256 hash algorithms as defined
+// in FIPS 180-2.
package sha256
import (
diff --git a/libgo/go/crypto/sha512/sha512.go b/libgo/go/crypto/sha512/sha512.go
index 7e9f330..78f5fe2 100644
--- a/libgo/go/crypto/sha512/sha512.go
+++ b/libgo/go/crypto/sha512/sha512.go
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// This package implements the SHA384 and SHA512 hash algorithms as defined in FIPS 180-2.
+// Package sha512 implements the SHA384 and SHA512 hash algorithms as defined
+// in FIPS 180-2.
package sha512
import (
diff --git a/libgo/go/crypto/subtle/constant_time.go b/libgo/go/crypto/subtle/constant_time.go
index a3d70b9..57dbe9d 100644
--- a/libgo/go/crypto/subtle/constant_time.go
+++ b/libgo/go/crypto/subtle/constant_time.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.
-// This package implements functions that are often useful in cryptographic
+// Package subtle implements functions that are often useful in cryptographic
// code but require careful thought to use correctly.
package subtle
diff --git a/libgo/go/crypto/tls/ca_set.go b/libgo/go/crypto/tls/ca_set.go
deleted file mode 100644
index ae00ac5..0000000
--- a/libgo/go/crypto/tls/ca_set.go
+++ /dev/null
@@ -1,89 +0,0 @@
-// 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 tls
-
-import (
- "crypto/x509"
- "encoding/pem"
- "strings"
-)
-
-// A CASet is a set of certificates.
-type CASet struct {
- bySubjectKeyId map[string][]*x509.Certificate
- byName map[string][]*x509.Certificate
-}
-
-// NewCASet returns a new, empty CASet.
-func NewCASet() *CASet {
- return &CASet{
- make(map[string][]*x509.Certificate),
- make(map[string][]*x509.Certificate),
- }
-}
-
-func nameToKey(name *x509.Name) string {
- return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName
-}
-
-// FindVerifiedParent attempts to find the certificate in s which has signed
-// the given certificate. If no such certificate can be found or the signature
-// doesn't match, it returns nil.
-func (s *CASet) FindVerifiedParent(cert *x509.Certificate) (parent *x509.Certificate) {
- var candidates []*x509.Certificate
-
- if len(cert.AuthorityKeyId) > 0 {
- candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
- }
- if len(candidates) == 0 {
- candidates = s.byName[nameToKey(&cert.Issuer)]
- }
-
- for _, c := range candidates {
- if cert.CheckSignatureFrom(c) == nil {
- return c
- }
- }
-
- return nil
-}
-
-// AddCert adds a certificate to the set
-func (s *CASet) AddCert(cert *x509.Certificate) {
- if len(cert.SubjectKeyId) > 0 {
- keyId := string(cert.SubjectKeyId)
- s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], cert)
- }
- name := nameToKey(&cert.Subject)
- s.byName[name] = append(s.byName[name], cert)
-}
-
-// SetFromPEM attempts to parse a series of PEM encoded root certificates. It
-// appends any certificates found to s and returns true if any certificates
-// were successfully parsed. On many Linux systems, /etc/ssl/cert.pem will
-// contains the system wide set of root CAs in a format suitable for this
-// function.
-func (s *CASet) SetFromPEM(pemCerts []byte) (ok bool) {
- for len(pemCerts) > 0 {
- var block *pem.Block
- block, pemCerts = pem.Decode(pemCerts)
- if block == nil {
- break
- }
- if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
- continue
- }
-
- cert, err := x509.ParseCertificate(block.Bytes)
- if err != nil {
- continue
- }
-
- s.AddCert(cert)
- ok = true
- }
-
- return
-}
diff --git a/libgo/go/crypto/tls/common.go b/libgo/go/crypto/tls/common.go
index c779234..0b26aae 100644
--- a/libgo/go/crypto/tls/common.go
+++ b/libgo/go/crypto/tls/common.go
@@ -100,6 +100,8 @@ type ConnectionState struct {
// the certificate chain that was presented by the other side
PeerCertificates []*x509.Certificate
+ // the verified certificate chains built from PeerCertificates.
+ VerifiedChains [][]*x509.Certificate
}
// A Config structure is used to configure a TLS client or server. After one
@@ -122,7 +124,7 @@ type Config struct {
// 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
+ RootCAs *x509.CertPool
// NextProtos is a list of supported, application level protocols.
NextProtos []string
@@ -158,7 +160,7 @@ func (c *Config) time() int64 {
return t()
}
-func (c *Config) rootCAs() *CASet {
+func (c *Config) rootCAs() *x509.CertPool {
s := c.RootCAs
if s == nil {
s = defaultRoots()
@@ -178,6 +180,9 @@ func (c *Config) cipherSuites() []uint16 {
type Certificate struct {
Certificate [][]byte
PrivateKey *rsa.PrivateKey
+ // OCSPStaple contains an optional OCSP response which will be served
+ // to clients that request it.
+ OCSPStaple []byte
}
// A TLS record.
@@ -221,7 +226,7 @@ var certFiles = []string{
var once sync.Once
-func defaultRoots() *CASet {
+func defaultRoots() *x509.CertPool {
once.Do(initDefaults)
return varDefaultRoots
}
@@ -236,14 +241,14 @@ func initDefaults() {
initDefaultCipherSuites()
}
-var varDefaultRoots *CASet
+var varDefaultRoots *x509.CertPool
func initDefaultRoots() {
- roots := NewCASet()
+ roots := x509.NewCertPool()
for _, file := range certFiles {
data, err := ioutil.ReadFile(file)
if err == nil {
- roots.SetFromPEM(data)
+ roots.AppendCertsFromPEM(data)
break
}
}
@@ -255,7 +260,7 @@ var varDefaultCipherSuites []uint16
func initDefaultCipherSuites() {
varDefaultCipherSuites = make([]uint16, len(cipherSuites))
i := 0
- for id, _ := range cipherSuites {
+ 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 b94e235..48d3f72 100644
--- a/libgo/go/crypto/tls/conn.go
+++ b/libgo/go/crypto/tls/conn.go
@@ -34,6 +34,9 @@ type Conn struct {
cipherSuite uint16
ocspResponse []byte // stapled OCSP response
peerCertificates []*x509.Certificate
+ // verifedChains contains the certificate chains that we built, as
+ // opposed to the ones presented by the server.
+ verifiedChains [][]*x509.Certificate
clientProtocol string
clientProtocolFallback bool
@@ -765,6 +768,7 @@ func (c *Conn) ConnectionState() ConnectionState {
state.NegotiatedProtocolIsMutual = !c.clientProtocolFallback
state.CipherSuite = c.cipherSuite
state.PeerCertificates = c.peerCertificates
+ state.VerifiedChains = c.verifiedChains
}
return state
diff --git a/libgo/go/crypto/tls/handshake_client.go b/libgo/go/crypto/tls/handshake_client.go
index 540b25c..c758c96 100644
--- a/libgo/go/crypto/tls/handshake_client.go
+++ b/libgo/go/crypto/tls/handshake_client.go
@@ -88,7 +88,6 @@ func (c *Conn) clientHandshake() os.Error {
finishedHash.Write(certMsg.marshal())
certs := make([]*x509.Certificate, len(certMsg.certificates))
- chain := NewCASet()
for i, asn1Data := range certMsg.certificates {
cert, err := x509.ParseCertificate(asn1Data)
if err != nil {
@@ -96,47 +95,29 @@ func (c *Conn) clientHandshake() os.Error {
return os.ErrorString("failed to parse certificate from server: " + err.String())
}
certs[i] = cert
- chain.AddCert(cert)
}
// If we don't have a root CA set configured then anything is accepted.
// TODO(rsc): Find certificates for OS X 10.6.
- for cur := certs[0]; c.config.RootCAs != nil; {
- parent := c.config.RootCAs.FindVerifiedParent(cur)
- if parent != nil {
- break
+ if c.config.RootCAs != nil {
+ opts := x509.VerifyOptions{
+ Roots: c.config.RootCAs,
+ CurrentTime: c.config.time(),
+ DNSName: c.config.ServerName,
+ Intermediates: x509.NewCertPool(),
}
- parent = chain.FindVerifiedParent(cur)
- if parent == nil {
- c.sendAlert(alertBadCertificate)
- return os.ErrorString("could not find root certificate for chain")
+ for i, cert := range certs {
+ if i == 0 {
+ continue
+ }
+ opts.Intermediates.AddCert(cert)
}
-
- if !parent.BasicConstraintsValid || !parent.IsCA {
+ c.verifiedChains, err = certs[0].Verify(opts)
+ if err != nil {
c.sendAlert(alertBadCertificate)
- return os.ErrorString("intermediate certificate does not have CA bit set")
+ return err
}
- // KeyUsage status flags are ignored. From Engineering
- // Security, Peter Gutmann: A European government CA marked its
- // signing certificates as being valid for encryption only, but
- // no-one noticed. Another European CA marked its signature
- // keys as not being valid for signatures. A different CA
- // marked its own trusted root certificate as being invalid for
- // certificate signing. Another national CA distributed a
- // certificate to be used to encrypt data for the country’s tax
- // authority that was marked as only being usable for digital
- // signatures but not for encryption. Yet another CA reversed
- // the order of the bit flags in the keyUsage due to confusion
- // over encoding endianness, essentially setting a random
- // keyUsage in certificates that it issued. Another CA created
- // a self-invalidating certificate by adding a certificate
- // policy statement stipulating that the certificate had to be
- // used strictly as specified in the keyUsage, and a keyUsage
- // containing a flag indicating that the RSA encryption key
- // could only be used for Diffie-Hellman key agreement.
-
- cur = parent
}
if _, ok := certs[0].PublicKey.(*rsa.PublicKey); !ok {
@@ -145,7 +126,7 @@ func (c *Conn) clientHandshake() os.Error {
c.peerCertificates = certs
- if serverHello.certStatus {
+ if serverHello.ocspStapling {
msg, err = c.readHandshake()
if err != nil {
return err
diff --git a/libgo/go/crypto/tls/handshake_messages.go b/libgo/go/crypto/tls/handshake_messages.go
index e5e8562..6645adc 100644
--- a/libgo/go/crypto/tls/handshake_messages.go
+++ b/libgo/go/crypto/tls/handshake_messages.go
@@ -306,7 +306,7 @@ type serverHelloMsg struct {
compressionMethod uint8
nextProtoNeg bool
nextProtos []string
- certStatus bool
+ ocspStapling bool
}
func (m *serverHelloMsg) marshal() []byte {
@@ -327,7 +327,7 @@ func (m *serverHelloMsg) marshal() []byte {
nextProtoLen += len(m.nextProtos)
extensionsLength += nextProtoLen
}
- if m.certStatus {
+ if m.ocspStapling {
numExtensions++
}
if numExtensions > 0 {
@@ -373,7 +373,7 @@ func (m *serverHelloMsg) marshal() []byte {
z = z[1+l:]
}
}
- if m.certStatus {
+ if m.ocspStapling {
z[0] = byte(extensionStatusRequest >> 8)
z[1] = byte(extensionStatusRequest)
z = z[4:]
@@ -406,7 +406,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
m.nextProtoNeg = false
m.nextProtos = nil
- m.certStatus = false
+ m.ocspStapling = false
if len(data) == 0 {
// ServerHello is optionally followed by extension data
@@ -450,7 +450,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
if length > 0 {
return false
}
- m.certStatus = true
+ m.ocspStapling = true
}
data = data[length:]
}
diff --git a/libgo/go/crypto/tls/handshake_messages_test.go b/libgo/go/crypto/tls/handshake_messages_test.go
index 0b93b89..23f729d 100644
--- a/libgo/go/crypto/tls/handshake_messages_test.go
+++ b/libgo/go/crypto/tls/handshake_messages_test.go
@@ -32,7 +32,7 @@ type testMessage interface {
func TestMarshalUnmarshal(t *testing.T) {
rand := rand.New(rand.NewSource(0))
for i, iface := range tests {
- ty := reflect.NewValue(iface).Type()
+ ty := reflect.ValueOf(iface).Type()
n := 100
if testing.Short() {
@@ -121,11 +121,11 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
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 {
+ for i := range m.supportedCurves {
m.supportedCurves[i] = uint16(rand.Intn(30000))
}
- return reflect.NewValue(m)
+ return reflect.ValueOf(m)
}
func (*serverHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
@@ -146,7 +146,7 @@ func (*serverHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
}
}
- return reflect.NewValue(m)
+ return reflect.ValueOf(m)
}
func (*certificateMsg) Generate(rand *rand.Rand, size int) reflect.Value {
@@ -156,7 +156,7 @@ func (*certificateMsg) Generate(rand *rand.Rand, size int) reflect.Value {
for i := 0; i < numCerts; i++ {
m.certificates[i] = randomBytes(rand.Intn(10)+1, rand)
}
- return reflect.NewValue(m)
+ return reflect.ValueOf(m)
}
func (*certificateRequestMsg) Generate(rand *rand.Rand, size int) reflect.Value {
@@ -167,13 +167,13 @@ func (*certificateRequestMsg) Generate(rand *rand.Rand, size int) reflect.Value
for i := 0; i < numCAs; i++ {
m.certificateAuthorities[i] = randomBytes(rand.Intn(15)+1, rand)
}
- return reflect.NewValue(m)
+ return reflect.ValueOf(m)
}
func (*certificateVerifyMsg) Generate(rand *rand.Rand, size int) reflect.Value {
m := &certificateVerifyMsg{}
m.signature = randomBytes(rand.Intn(15)+1, rand)
- return reflect.NewValue(m)
+ return reflect.ValueOf(m)
}
func (*certificateStatusMsg) Generate(rand *rand.Rand, size int) reflect.Value {
@@ -184,23 +184,23 @@ func (*certificateStatusMsg) Generate(rand *rand.Rand, size int) reflect.Value {
} else {
m.statusType = 42
}
- return reflect.NewValue(m)
+ return reflect.ValueOf(m)
}
func (*clientKeyExchangeMsg) Generate(rand *rand.Rand, size int) reflect.Value {
m := &clientKeyExchangeMsg{}
m.ciphertext = randomBytes(rand.Intn(1000)+1, rand)
- return reflect.NewValue(m)
+ return reflect.ValueOf(m)
}
func (*finishedMsg) Generate(rand *rand.Rand, size int) reflect.Value {
m := &finishedMsg{}
m.verifyData = randomBytes(12, rand)
- return reflect.NewValue(m)
+ return reflect.ValueOf(m)
}
func (*nextProtoMsg) Generate(rand *rand.Rand, size int) reflect.Value {
m := &nextProtoMsg{}
m.proto = randomString(rand.Intn(255), rand)
- return reflect.NewValue(m)
+ return reflect.ValueOf(m)
}
diff --git a/libgo/go/crypto/tls/handshake_server.go b/libgo/go/crypto/tls/handshake_server.go
index 809c8c1..37c8d15 100644
--- a/libgo/go/crypto/tls/handshake_server.go
+++ b/libgo/go/crypto/tls/handshake_server.go
@@ -103,6 +103,9 @@ FindCipherSuite:
hello.nextProtoNeg = true
hello.nextProtos = config.NextProtos
}
+ if clientHello.ocspStapling && len(config.Certificates[0].OCSPStaple) > 0 {
+ hello.ocspStapling = true
+ }
finishedHash.Write(hello.marshal())
c.writeRecord(recordTypeHandshake, hello.marshal())
@@ -116,6 +119,14 @@ FindCipherSuite:
finishedHash.Write(certMsg.marshal())
c.writeRecord(recordTypeHandshake, certMsg.marshal())
+ if hello.ocspStapling {
+ certStatus := new(certificateStatusMsg)
+ certStatus.statusType = statusTypeOCSP
+ certStatus.response = config.Certificates[0].OCSPStaple
+ finishedHash.Write(certStatus.marshal())
+ c.writeRecord(recordTypeHandshake, certStatus.marshal())
+ }
+
keyAgreement := suite.ka()
skx, err := keyAgreement.generateServerKeyExchange(config, clientHello, hello)
diff --git a/libgo/go/crypto/tls/handshake_server_test.go b/libgo/go/crypto/tls/handshake_server_test.go
index 6beb6a9..5a1e754 100644
--- a/libgo/go/crypto/tls/handshake_server_test.go
+++ b/libgo/go/crypto/tls/handshake_server_test.go
@@ -188,8 +188,10 @@ var testPrivateKey = &rsa.PrivateKey{
E: 65537,
},
D: bigFromString("29354450337804273969007277378287027274721892607543397931919078829901848876371746653677097639302788129485893852488285045793268732234230875671682624082413996177431586734171663258657462237320300610850244186316880055243099640544518318093544057213190320837094958164973959123058337475052510833916491060913053867729"),
- P: bigFromString("11969277782311800166562047708379380720136961987713178380670422671426759650127150688426177829077494755200794297055316163155755835813760102405344560929062149"),
- Q: bigFromString("10998999429884441391899182616418192492905073053684657075974935218461686523870125521822756579792315215543092255516093840728890783887287417039645833477273829"),
+ Primes: []*big.Int{
+ bigFromString("11969277782311800166562047708379380720136961987713178380670422671426759650127150688426177829077494755200794297055316163155755835813760102405344560929062149"),
+ bigFromString("10998999429884441391899182616418192492905073053684657075974935218461686523870125521822756579792315215543092255516093840728890783887287417039645833477273829"),
+ },
}
// Script of interaction with gnutls implementation.
diff --git a/libgo/go/crypto/tls/tls.go b/libgo/go/crypto/tls/tls.go
index 7de44bb..7d0bb9f 100644
--- a/libgo/go/crypto/tls/tls.go
+++ b/libgo/go/crypto/tls/tls.go
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// This package partially implements the TLS 1.1 protocol, as specified in RFC 4346.
+// Package tls partially implements the TLS 1.1 protocol, as specified in RFC
+// 4346.
package tls
import (
diff --git a/libgo/go/crypto/twofish/twofish.go b/libgo/go/crypto/twofish/twofish.go
index 62253e7..9303f03 100644
--- a/libgo/go/crypto/twofish/twofish.go
+++ b/libgo/go/crypto/twofish/twofish.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.
-// This package implements Bruce Schneier's Twofish encryption algorithm.
+// Package twofish implements Bruce Schneier's Twofish encryption algorithm.
package twofish
// Twofish is defined in http://www.schneier.com/paper-twofish-paper.pdf [TWOFISH]
diff --git a/libgo/go/crypto/x509/cert_pool.go b/libgo/go/crypto/x509/cert_pool.go
new file mode 100644
index 0000000..c295fd9
--- /dev/null
+++ b/libgo/go/crypto/x509/cert_pool.go
@@ -0,0 +1,105 @@
+// 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 x509
+
+import (
+ "encoding/pem"
+ "strings"
+)
+
+// Roots is a set of certificates.
+type CertPool struct {
+ bySubjectKeyId map[string][]int
+ byName map[string][]int
+ certs []*Certificate
+}
+
+// NewCertPool returns a new, empty CertPool.
+func NewCertPool() *CertPool {
+ return &CertPool{
+ make(map[string][]int),
+ make(map[string][]int),
+ nil,
+ }
+}
+
+func nameToKey(name *Name) string {
+ return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName
+}
+
+// findVerifiedParents attempts to find certificates in s which have signed the
+// given certificate. If no such certificate can be found or the signature
+// doesn't match, it returns nil.
+func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int) {
+ var candidates []int
+
+ if len(cert.AuthorityKeyId) > 0 {
+ candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
+ }
+ if len(candidates) == 0 {
+ candidates = s.byName[nameToKey(&cert.Issuer)]
+ }
+
+ for _, c := range candidates {
+ if cert.CheckSignatureFrom(s.certs[c]) == nil {
+ parents = append(parents, c)
+ }
+ }
+
+ return
+}
+
+// AddCert adds a certificate to a pool.
+func (s *CertPool) AddCert(cert *Certificate) {
+ if cert == nil {
+ panic("adding nil Certificate to CertPool")
+ }
+
+ // Check that the certificate isn't being added twice.
+ for _, c := range s.certs {
+ if c.Equal(cert) {
+ return
+ }
+ }
+
+ n := len(s.certs)
+ s.certs = append(s.certs, cert)
+
+ if len(cert.SubjectKeyId) > 0 {
+ keyId := string(cert.SubjectKeyId)
+ s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n)
+ }
+ name := nameToKey(&cert.Subject)
+ s.byName[name] = append(s.byName[name], n)
+}
+
+// AppendCertsFromPEM attempts to parse a series of PEM encoded root
+// certificates. It appends any certificates found to s and returns true if any
+// certificates were successfully parsed.
+//
+// On many Linux systems, /etc/ssl/cert.pem will contains the system wide set
+// of root CAs in a format suitable for this function.
+func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
+ for len(pemCerts) > 0 {
+ var block *pem.Block
+ block, pemCerts = pem.Decode(pemCerts)
+ if block == nil {
+ break
+ }
+ if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
+ continue
+ }
+
+ cert, err := ParseCertificate(block.Bytes)
+ if err != nil {
+ continue
+ }
+
+ s.AddCert(cert)
+ ok = true
+ }
+
+ return
+}
diff --git a/libgo/go/crypto/x509/verify.go b/libgo/go/crypto/x509/verify.go
new file mode 100644
index 0000000..9145880
--- /dev/null
+++ b/libgo/go/crypto/x509/verify.go
@@ -0,0 +1,239 @@
+// 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 x509
+
+import (
+ "os"
+ "strings"
+ "time"
+)
+
+type InvalidReason int
+
+const (
+ // NotAuthorizedToSign results when a certificate is signed by another
+ // which isn't marked as a CA certificate.
+ NotAuthorizedToSign InvalidReason = iota
+ // Expired results when a certificate has expired, based on the time
+ // given in the VerifyOptions.
+ Expired
+ // CANotAuthorizedForThisName results when an intermediate or root
+ // certificate has a name constraint which doesn't include the name
+ // being checked.
+ CANotAuthorizedForThisName
+)
+
+// CertificateInvalidError results when an odd error occurs. Users of this
+// library probably want to handle all these errors uniformly.
+type CertificateInvalidError struct {
+ Cert *Certificate
+ Reason InvalidReason
+}
+
+func (e CertificateInvalidError) String() string {
+ switch e.Reason {
+ case NotAuthorizedToSign:
+ return "x509: certificate is not authorized to sign other other certificates"
+ case Expired:
+ return "x509: certificate has expired or is not yet valid"
+ case CANotAuthorizedForThisName:
+ return "x509: a root or intermediate certificate is not authorized to sign in this domain"
+ }
+ return "x509: unknown error"
+}
+
+// HostnameError results when the set of authorized names doesn't match the
+// requested name.
+type HostnameError struct {
+ Certificate *Certificate
+ Host string
+}
+
+func (h HostnameError) String() string {
+ var valid string
+ c := h.Certificate
+ if len(c.DNSNames) > 0 {
+ valid = strings.Join(c.DNSNames, ", ")
+ } else {
+ valid = c.Subject.CommonName
+ }
+ return "certificate is valid for " + valid + ", not " + h.Host
+}
+
+
+// UnknownAuthorityError results when the certificate issuer is unknown
+type UnknownAuthorityError struct {
+ cert *Certificate
+}
+
+func (e UnknownAuthorityError) String() string {
+ return "x509: certificate signed by unknown authority"
+}
+
+// VerifyOptions contains parameters for Certificate.Verify. It's a structure
+// because other PKIX verification APIs have ended up needing many options.
+type VerifyOptions struct {
+ DNSName string
+ Intermediates *CertPool
+ Roots *CertPool
+ CurrentTime int64 // if 0, the current system time is used.
+}
+
+const (
+ leafCertificate = iota
+ intermediateCertificate
+ rootCertificate
+)
+
+// isValid performs validity checks on the c.
+func (c *Certificate) isValid(certType int, opts *VerifyOptions) os.Error {
+ if opts.CurrentTime < c.NotBefore.Seconds() ||
+ opts.CurrentTime > c.NotAfter.Seconds() {
+ return CertificateInvalidError{c, Expired}
+ }
+
+ if len(c.PermittedDNSDomains) > 0 {
+ for _, domain := range c.PermittedDNSDomains {
+ if opts.DNSName == domain ||
+ (strings.HasSuffix(opts.DNSName, domain) &&
+ len(opts.DNSName) >= 1+len(domain) &&
+ opts.DNSName[len(opts.DNSName)-len(domain)-1] == '.') {
+ continue
+ }
+
+ return CertificateInvalidError{c, CANotAuthorizedForThisName}
+ }
+ }
+
+ // KeyUsage status flags are ignored. From Engineering Security, Peter
+ // Gutmann: A European government CA marked its signing certificates as
+ // being valid for encryption only, but no-one noticed. Another
+ // European CA marked its signature keys as not being valid for
+ // signatures. A different CA marked its own trusted root certificate
+ // as being invalid for certificate signing. Another national CA
+ // distributed a certificate to be used to encrypt data for the
+ // country’s tax authority that was marked as only being usable for
+ // digital signatures but not for encryption. Yet another CA reversed
+ // the order of the bit flags in the keyUsage due to confusion over
+ // encoding endianness, essentially setting a random keyUsage in
+ // certificates that it issued. Another CA created a self-invalidating
+ // certificate by adding a certificate policy statement stipulating
+ // that the certificate had to be used strictly as specified in the
+ // keyUsage, and a keyUsage containing a flag indicating that the RSA
+ // encryption key could only be used for Diffie-Hellman key agreement.
+
+ if certType == intermediateCertificate && (!c.BasicConstraintsValid || !c.IsCA) {
+ return CertificateInvalidError{c, NotAuthorizedToSign}
+ }
+
+ return nil
+}
+
+// Verify attempts to verify c by building one or more chains from c to a
+// certificate in opts.roots, using certificates in opts.Intermediates if
+// needed. If successful, it returns one or chains where the first element of
+// the chain is c and the last element is from opts.Roots.
+//
+// WARNING: this doesn't do any revocation checking.
+func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err os.Error) {
+ if opts.CurrentTime == 0 {
+ opts.CurrentTime = time.Seconds()
+ }
+ err = c.isValid(leafCertificate, &opts)
+ if err != nil {
+ return
+ }
+ if len(opts.DNSName) > 0 {
+ err = c.VerifyHostname(opts.DNSName)
+ if err != nil {
+ return
+ }
+ }
+ return c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts)
+}
+
+func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate {
+ n := make([]*Certificate, len(chain)+1)
+ copy(n, chain)
+ n[len(chain)] = cert
+ return n
+}
+
+func (c *Certificate) buildChains(cache map[int][][]*Certificate, currentChain []*Certificate, opts *VerifyOptions) (chains [][]*Certificate, err os.Error) {
+ for _, rootNum := range opts.Roots.findVerifiedParents(c) {
+ root := opts.Roots.certs[rootNum]
+ err = root.isValid(rootCertificate, opts)
+ if err != nil {
+ continue
+ }
+ chains = append(chains, appendToFreshChain(currentChain, root))
+ }
+
+ for _, intermediateNum := range opts.Intermediates.findVerifiedParents(c) {
+ intermediate := opts.Intermediates.certs[intermediateNum]
+ err = intermediate.isValid(intermediateCertificate, opts)
+ if err != nil {
+ continue
+ }
+ var childChains [][]*Certificate
+ childChains, ok := cache[intermediateNum]
+ if !ok {
+ childChains, err = intermediate.buildChains(cache, appendToFreshChain(currentChain, intermediate), opts)
+ cache[intermediateNum] = childChains
+ }
+ chains = append(chains, childChains...)
+ }
+
+ if len(chains) > 0 {
+ err = nil
+ }
+
+ if len(chains) == 0 && err == nil {
+ err = UnknownAuthorityError{c}
+ }
+
+ return
+}
+
+func matchHostnames(pattern, host string) bool {
+ if len(pattern) == 0 || len(host) == 0 {
+ return false
+ }
+
+ patternParts := strings.Split(pattern, ".", -1)
+ hostParts := strings.Split(host, ".", -1)
+
+ if len(patternParts) != len(hostParts) {
+ return false
+ }
+
+ for i, patternPart := range patternParts {
+ if patternPart == "*" {
+ continue
+ }
+ if patternPart != hostParts[i] {
+ return false
+ }
+ }
+
+ return true
+}
+
+// VerifyHostname returns nil if c is a valid certificate for the named host.
+// Otherwise it returns an os.Error describing the mismatch.
+func (c *Certificate) VerifyHostname(h string) os.Error {
+ if len(c.DNSNames) > 0 {
+ for _, match := range c.DNSNames {
+ if matchHostnames(match, h) {
+ return nil
+ }
+ }
+ // If Subject Alt Name is given, we ignore the common name.
+ } else if matchHostnames(c.Subject.CommonName, h) {
+ return nil
+ }
+
+ return HostnameError{c, h}
+}
diff --git a/libgo/go/crypto/x509/verify_test.go b/libgo/go/crypto/x509/verify_test.go
new file mode 100644
index 0000000..6a103dc
--- /dev/null
+++ b/libgo/go/crypto/x509/verify_test.go
@@ -0,0 +1,390 @@
+// 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 x509
+
+import (
+ "encoding/pem"
+ "os"
+ "strings"
+ "testing"
+)
+
+type verifyTest struct {
+ leaf string
+ intermediates []string
+ roots []string
+ currentTime int64
+ dnsName string
+
+ errorCallback func(*testing.T, int, os.Error) bool
+ expectedChains [][]string
+}
+
+var verifyTests = []verifyTest{
+ {
+ leaf: googleLeaf,
+ intermediates: []string{thawteIntermediate},
+ roots: []string{verisignRoot},
+ currentTime: 1302726541,
+ dnsName: "www.google.com",
+
+ expectedChains: [][]string{
+ []string{"Google", "Thawte", "VeriSign"},
+ },
+ },
+ {
+ leaf: googleLeaf,
+ intermediates: []string{thawteIntermediate},
+ roots: []string{verisignRoot},
+ currentTime: 1302726541,
+ dnsName: "www.example.com",
+
+ errorCallback: expectHostnameError,
+ },
+ {
+ leaf: googleLeaf,
+ intermediates: []string{thawteIntermediate},
+ roots: []string{verisignRoot},
+ currentTime: 1,
+ dnsName: "www.example.com",
+
+ errorCallback: expectExpired,
+ },
+ {
+ leaf: googleLeaf,
+ roots: []string{verisignRoot},
+ currentTime: 1302726541,
+ dnsName: "www.google.com",
+
+ errorCallback: expectAuthorityUnknown,
+ },
+ {
+ leaf: googleLeaf,
+ intermediates: []string{verisignRoot, thawteIntermediate},
+ roots: []string{verisignRoot},
+ currentTime: 1302726541,
+ dnsName: "www.google.com",
+
+ expectedChains: [][]string{
+ []string{"Google", "Thawte", "VeriSign"},
+ },
+ },
+ {
+ leaf: googleLeaf,
+ intermediates: []string{verisignRoot, thawteIntermediate},
+ roots: []string{verisignRoot},
+ currentTime: 1302726541,
+
+ expectedChains: [][]string{
+ []string{"Google", "Thawte", "VeriSign"},
+ },
+ },
+ {
+ leaf: dnssecExpLeaf,
+ intermediates: []string{startComIntermediate},
+ roots: []string{startComRoot},
+ currentTime: 1302726541,
+
+ expectedChains: [][]string{
+ []string{"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"},
+ },
+ },
+}
+
+func expectHostnameError(t *testing.T, i int, err os.Error) (ok bool) {
+ if _, ok := err.(HostnameError); !ok {
+ t.Errorf("#%d: error was not a HostnameError: %s", i, err)
+ return false
+ }
+ return true
+}
+
+func expectExpired(t *testing.T, i int, err os.Error) (ok bool) {
+ if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != Expired {
+ t.Errorf("#%d: error was not Expired: %s", i, err)
+ return false
+ }
+ return true
+}
+
+func expectAuthorityUnknown(t *testing.T, i int, err os.Error) (ok bool) {
+ if _, ok := err.(UnknownAuthorityError); !ok {
+ t.Errorf("#%d: error was not UnknownAuthorityError: %s", i, err)
+ return false
+ }
+ return true
+}
+
+func certificateFromPEM(pemBytes string) (*Certificate, os.Error) {
+ block, _ := pem.Decode([]byte(pemBytes))
+ if block == nil {
+ return nil, os.ErrorString("failed to decode PEM")
+ }
+ return ParseCertificate(block.Bytes)
+}
+
+func TestVerify(t *testing.T) {
+ for i, test := range verifyTests {
+ opts := VerifyOptions{
+ Roots: NewCertPool(),
+ Intermediates: NewCertPool(),
+ DNSName: test.dnsName,
+ CurrentTime: test.currentTime,
+ }
+
+ for j, root := range test.roots {
+ ok := opts.Roots.AppendCertsFromPEM([]byte(root))
+ if !ok {
+ t.Errorf("#%d: failed to parse root #%d", i, j)
+ return
+ }
+ }
+
+ for j, intermediate := range test.intermediates {
+ ok := opts.Intermediates.AppendCertsFromPEM([]byte(intermediate))
+ if !ok {
+ t.Errorf("#%d: failed to parse intermediate #%d", i, j)
+ return
+ }
+ }
+
+ leaf, err := certificateFromPEM(test.leaf)
+ if err != nil {
+ t.Errorf("#%d: failed to parse leaf: %s", i, err)
+ return
+ }
+
+ chains, err := leaf.Verify(opts)
+
+ if test.errorCallback == nil && err != nil {
+ t.Errorf("#%d: unexpected error: %s", i, err)
+ }
+ if test.errorCallback != nil {
+ if !test.errorCallback(t, i, err) {
+ return
+ }
+ }
+
+ if len(chains) != len(test.expectedChains) {
+ t.Errorf("#%d: wanted %d chains, got %d", i, len(test.expectedChains), len(chains))
+ }
+
+ // We check that each returned chain matches a chain from
+ // expectedChains but an entry in expectedChains can't match
+ // two chains.
+ seenChains := make([]bool, len(chains))
+ NextOutputChain:
+ for _, chain := range chains {
+ TryNextExpected:
+ for j, expectedChain := range test.expectedChains {
+ if seenChains[j] {
+ continue
+ }
+ if len(chain) != len(expectedChain) {
+ continue
+ }
+ for k, cert := range chain {
+ if strings.Index(nameToKey(&cert.Subject), expectedChain[k]) == -1 {
+ continue TryNextExpected
+ }
+ }
+ // we matched
+ seenChains[j] = true
+ continue NextOutputChain
+ }
+ t.Errorf("#%d: No expected chain matched %s", i, chainToDebugString(chain))
+ }
+ }
+}
+
+func chainToDebugString(chain []*Certificate) string {
+ var chainStr string
+ for _, cert := range chain {
+ if len(chainStr) > 0 {
+ chainStr += " -> "
+ }
+ chainStr += nameToKey(&cert.Subject)
+ }
+ return chainStr
+}
+
+const verisignRoot = `-----BEGIN CERTIFICATE-----
+MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG
+A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
+cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
+MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
+BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
+YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
+BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
+I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
+CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do
+lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc
+AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k
+-----END CERTIFICATE-----
+`
+
+const thawteIntermediate = `-----BEGIN CERTIFICATE-----
+MIIDIzCCAoygAwIBAgIEMAAAAjANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDMgUHVi
+bGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNTEzMDAw
+MDAwWhcNMTQwNTEyMjM1OTU5WjBMMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhh
+d3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBD
+QTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1NNn0I0Vf67NMf59HZGhPwtx
+PKzMyGT7Y/wySweUvW+Aui/hBJPAM/wJMyPpC3QrccQDxtLN4i/1CWPN/0ilAL/g
+5/OIty0y3pg25gqtAHvEZEo7hHUD8nCSfQ5i9SGraTaEMXWQ+L/HbIgbBpV8yeWo
+3nWhLHpo39XKHIdYYBkCAwEAAaOB/jCB+zASBgNVHRMBAf8ECDAGAQH/AgEAMAsG
+A1UdDwQEAwIBBjARBglghkgBhvhCAQEEBAMCAQYwKAYDVR0RBCEwH6QdMBsxGTAX
+BgNVBAMTEFByaXZhdGVMYWJlbDMtMTUwMQYDVR0fBCowKDAmoCSgIoYgaHR0cDov
+L2NybC52ZXJpc2lnbi5jb20vcGNhMy5jcmwwMgYIKwYBBQUHAQEEJjAkMCIGCCsG
+AQUFBzABhhZodHRwOi8vb2NzcC50aGF3dGUuY29tMDQGA1UdJQQtMCsGCCsGAQUF
+BwMBBggrBgEFBQcDAgYJYIZIAYb4QgQBBgpghkgBhvhFAQgBMA0GCSqGSIb3DQEB
+BQUAA4GBAFWsY+reod3SkF+fC852vhNRj5PZBSvIG3dLrWlQoe7e3P3bB+noOZTc
+q3J5Lwa/q4FwxKjt6lM07e8eU9kGx1Yr0Vz00YqOtCuxN5BICEIlxT6Ky3/rbwTR
+bcV0oveifHtgPHfNDs5IAn8BL7abN+AqKjbc1YXWrOU/VG+WHgWv
+-----END CERTIFICATE-----
+`
+
+const googleLeaf = `-----BEGIN CERTIFICATE-----
+MIIDITCCAoqgAwIBAgIQL9+89q6RUm0PmqPfQDQ+mjANBgkqhkiG9w0BAQUFADBM
+MQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkg
+THRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBDQTAeFw0wOTEyMTgwMDAwMDBaFw0x
+MTEyMTgyMzU5NTlaMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh
+MRYwFAYDVQQHFA1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKFApHb29nbGUgSW5jMRcw
+FQYDVQQDFA53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEA6PmGD5D6htffvXImttdEAoN4c9kCKO+IRTn7EOh8rqk41XXGOOsKFQebg+jN
+gtXj9xVoRaELGYW84u+E593y17iYwqG7tcFR39SDAqc9BkJb4SLD3muFXxzW2k6L
+05vuuWciKh0R73mkszeK9P4Y/bz5RiNQl/Os/CRGK1w7t0UCAwEAAaOB5zCB5DAM
+BgNVHRMBAf8EAjAAMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwudGhhd3Rl
+LmNvbS9UaGF3dGVTR0NDQS5jcmwwKAYDVR0lBCEwHwYIKwYBBQUHAwEGCCsGAQUF
+BwMCBglghkgBhvhCBAEwcgYIKwYBBQUHAQEEZjBkMCIGCCsGAQUFBzABhhZodHRw
+Oi8vb2NzcC50aGF3dGUuY29tMD4GCCsGAQUFBzAChjJodHRwOi8vd3d3LnRoYXd0
+ZS5jb20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAQUF
+AAOBgQCfQ89bxFApsb/isJr/aiEdLRLDLE5a+RLizrmCUi3nHX4adpaQedEkUjh5
+u2ONgJd8IyAPkU0Wueru9G2Jysa9zCRo1kNbzipYvzwY4OA8Ys+WAi0oR1A04Se6
+z5nRUP8pJcA2NhUzUnC+MY+f6H/nEQyNv4SgQhqAibAxWEEHXw==
+-----END CERTIFICATE-----`
+
+const dnssecExpLeaf = `-----BEGIN CERTIFICATE-----
+MIIGzTCCBbWgAwIBAgIDAdD6MA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ
+TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0
+YWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg
+MSBQcmltYXJ5IEludGVybWVkaWF0ZSBTZXJ2ZXIgQ0EwHhcNMTAwNzA0MTQ1MjQ1
+WhcNMTEwNzA1MTA1NzA0WjCBwTEgMB4GA1UEDRMXMjIxMTM3LWxpOWE5dHhJRzZM
+NnNyVFMxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVQZXJzb25hIE5vdCBWYWxpZGF0
+ZWQxKTAnBgNVBAsTIFN0YXJ0Q29tIEZyZWUgQ2VydGlmaWNhdGUgTWVtYmVyMRsw
+GQYDVQQDExJ3d3cuZG5zc2VjLWV4cC5vcmcxKDAmBgkqhkiG9w0BCQEWGWhvc3Rt
+YXN0ZXJAZG5zc2VjLWV4cC5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQDEdF/22vaxrPbqpgVYMWi+alfpzBctpbfLBdPGuqOazJdCT0NbWcK8/+B4
+X6OlSOURNIlwLzhkmwVsWdVv6dVSaN7d4yI/fJkvgfDB9+au+iBJb6Pcz8ULBfe6
+D8HVvqKdORp6INzHz71z0sghxrQ0EAEkoWAZLh+kcn2ZHdcmZaBNUfjmGbyU6PRt
+RjdqoP+owIaC1aktBN7zl4uO7cRjlYFdusINrh2kPP02KAx2W84xjxX1uyj6oS6e
+7eBfvcwe8czW/N1rbE0CoR7h9+HnIrjnVG9RhBiZEiw3mUmF++Up26+4KTdRKbu3
++BL4yMpfd66z0+zzqu+HkvyLpFn5AgMBAAGjggL/MIIC+zAJBgNVHRMEAjAAMAsG
+A1UdDwQEAwIDqDATBgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4EFgQUy04I5guM
+drzfh2JQaXhgV86+4jUwHwYDVR0jBBgwFoAU60I00Jiwq5/0G2sI98xkLu8OLEUw
+LQYDVR0RBCYwJIISd3d3LmRuc3NlYy1leHAub3Jngg5kbnNzZWMtZXhwLm9yZzCC
+AUIGA1UdIASCATkwggE1MIIBMQYLKwYBBAGBtTcBAgIwggEgMC4GCCsGAQUFBwIB
+FiJodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9wb2xpY3kucGRmMDQGCCsGAQUFBwIB
+FihodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9pbnRlcm1lZGlhdGUucGRmMIG3Bggr
+BgEFBQcCAjCBqjAUFg1TdGFydENvbSBMdGQuMAMCAQEagZFMaW1pdGVkIExpYWJp
+bGl0eSwgc2VlIHNlY3Rpb24gKkxlZ2FsIExpbWl0YXRpb25zKiBvZiB0aGUgU3Rh
+cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUG9saWN5IGF2YWlsYWJsZSBh
+dCBodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9wb2xpY3kucGRmMGEGA1UdHwRaMFgw
+KqAooCaGJGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2NydDEtY3JsLmNybDAqoCig
+JoYkaHR0cDovL2NybC5zdGFydHNzbC5jb20vY3J0MS1jcmwuY3JsMIGOBggrBgEF
+BQcBAQSBgTB/MDkGCCsGAQUFBzABhi1odHRwOi8vb2NzcC5zdGFydHNzbC5jb20v
+c3ViL2NsYXNzMS9zZXJ2ZXIvY2EwQgYIKwYBBQUHMAKGNmh0dHA6Ly93d3cuc3Rh
+cnRzc2wuY29tL2NlcnRzL3N1Yi5jbGFzczEuc2VydmVyLmNhLmNydDAjBgNVHRIE
+HDAahhhodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS8wDQYJKoZIhvcNAQEFBQADggEB
+ACXj6SB59KRJPenn6gUdGEqcta97U769SATyiQ87i9er64qLwvIGLMa3o2Rcgl2Y
+kghUeyLdN/EXyFBYA8L8uvZREPoc7EZukpT/ZDLXy9i2S0jkOxvF2fD/XLbcjGjM
+iEYG1/6ASw0ri9C0k4oDDoJLCoeH9++yqF7SFCCMcDkJqiAGXNb4euDpa8vCCtEQ
+CSS+ObZbfkreRt3cNCf5LfCXe9OsTnCfc8Cuq81c0oLaG+SmaLUQNBuToq8e9/Zm
++b+/a3RVjxmkV5OCcGVBxsXNDn54Q6wsdw0TBMcjwoEndzpLS7yWgFbbkq5ZiGpw
+Qibb2+CfKuQ+WFV1GkVQmVA=
+-----END CERTIFICATE-----`
+
+const startComIntermediate = `-----BEGIN CERTIFICATE-----
+MIIGNDCCBBygAwIBAgIBGDANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW
+MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
+Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMDcxMDI0MjA1NDE3WhcNMTcxMDI0MjA1NDE3WjCB
+jDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzApBgNVBAsT
+IlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxODA2BgNVBAMTL1N0
+YXJ0Q29tIENsYXNzIDEgUHJpbWFyeSBJbnRlcm1lZGlhdGUgU2VydmVyIENBMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtonGrO8JUngHrJJj0PREGBiE
+gFYfka7hh/oyULTTRwbw5gdfcA4Q9x3AzhA2NIVaD5Ksg8asWFI/ujjo/OenJOJA
+pgh2wJJuniptTT9uYSAK21ne0n1jsz5G/vohURjXzTCm7QduO3CHtPn66+6CPAVv
+kvek3AowHpNz/gfK11+AnSJYUq4G2ouHI2mw5CrY6oPSvfNx23BaKA+vWjhwRRI/
+ME3NO68X5Q/LoKldSKqxYVDLNM08XMML6BDAjJvwAwNi/rJsPnIO7hxDKslIDlc5
+xDEhyBDBLIf+VJVSH1I8MRKbf+fAoKVZ1eKPPvDVqOHXcDGpxLPPr21TLwb0pwID
+AQABo4IBrTCCAakwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
+VR0OBBYEFOtCNNCYsKuf9BtrCPfMZC7vDixFMB8GA1UdIwQYMBaAFE4L7xqkQFul
+F2mHMMo0aEPQQa7yMGYGCCsGAQUFBwEBBFowWDAnBggrBgEFBQcwAYYbaHR0cDov
+L29jc3Auc3RhcnRzc2wuY29tL2NhMC0GCCsGAQUFBzAChiFodHRwOi8vd3d3LnN0
+YXJ0c3NsLmNvbS9zZnNjYS5jcnQwWwYDVR0fBFQwUjAnoCWgI4YhaHR0cDovL3d3
+dy5zdGFydHNzbC5jb20vc2ZzY2EuY3JsMCegJaAjhiFodHRwOi8vY3JsLnN0YXJ0
+c3NsLmNvbS9zZnNjYS5jcmwwgYAGA1UdIAR5MHcwdQYLKwYBBAGBtTcBAgEwZjAu
+BggrBgEFBQcCARYiaHR0cDovL3d3dy5zdGFydHNzbC5jb20vcG9saWN5LnBkZjA0
+BggrBgEFBQcCARYoaHR0cDovL3d3dy5zdGFydHNzbC5jb20vaW50ZXJtZWRpYXRl
+LnBkZjANBgkqhkiG9w0BAQUFAAOCAgEAIQlJPqWIbuALi0jaMU2P91ZXouHTYlfp
+tVbzhUV1O+VQHwSL5qBaPucAroXQ+/8gA2TLrQLhxpFy+KNN1t7ozD+hiqLjfDen
+xk+PNdb01m4Ge90h2c9W/8swIkn+iQTzheWq8ecf6HWQTd35RvdCNPdFWAwRDYSw
+xtpdPvkBnufh2lWVvnQce/xNFE+sflVHfXv0pQ1JHpXo9xLBzP92piVH0PN1Nb6X
+t1gW66pceG/sUzCv6gRNzKkC4/C2BBL2MLERPZBOVmTX3DxDX3M570uvh+v2/miI
+RHLq0gfGabDBoYvvF0nXYbFFSF87ICHpW7LM9NfpMfULFWE7epTj69m8f5SuauNi
+YpaoZHy4h/OZMn6SolK+u/hlz8nyMPyLwcKmltdfieFcNID1j0cHL7SRv7Gifl9L
+WtBbnySGBVFaaQNlQ0lxxeBvlDRr9hvYqbBMflPrj0jfyjO1SPo2ShpTpjMM0InN
+SRXNiTE8kMBy12VLUjWKRhFEuT2OKGWmPnmeXAhEKa2wNREuIU640ucQPl2Eg7PD
+wuTSxv0JS3QJ3fGz0xk+gA2iCxnwOOfFwq/iI9th4p1cbiCJSS4jarJiwUW0n6+L
+p/EiO/h94pDQehn7Skzj0n1fSoMD7SfWI55rjbRZotnvbIIp3XUZPD9MEI3vu3Un
+0q6Dp6jOW6c=
+-----END CERTIFICATE-----`
+
+const startComRoot = `-----BEGIN CERTIFICATE-----
+MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW
+MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
+Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9
+MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi
+U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh
+cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk
+pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf
+OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C
+Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT
+Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi
+HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM
+Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w
++2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+
+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3
+Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B
+26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID
+AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE
+FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j
+ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js
+LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM
+BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0
+Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy
+dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh
+cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh
+YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg
+dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp
+bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ
+YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT
+TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ
+9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8
+jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW
+FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz
+ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1
+ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L
+EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu
+L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq
+yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC
+O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V
+um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh
+NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14=
+-----END CERTIFICATE-----`
diff --git a/libgo/go/crypto/x509/x509.go b/libgo/go/crypto/x509/x509.go
index 6825030..d0c5a26 100644
--- a/libgo/go/crypto/x509/x509.go
+++ b/libgo/go/crypto/x509/x509.go
@@ -2,12 +2,13 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// This package parses X.509-encoded keys and certificates.
+// Package x509 parses X.509-encoded keys and certificates.
package x509
import (
"asn1"
"big"
+ "bytes"
"container/vector"
"crypto"
"crypto/rsa"
@@ -15,7 +16,6 @@ import (
"hash"
"io"
"os"
- "strings"
"time"
)
@@ -27,6 +27,20 @@ type pkcs1PrivateKey struct {
D asn1.RawValue
P asn1.RawValue
Q asn1.RawValue
+ // We ignore these values, if present, because rsa will calculate them.
+ Dp asn1.RawValue "optional"
+ Dq asn1.RawValue "optional"
+ Qinv asn1.RawValue "optional"
+
+ AdditionalPrimes []pkcs1AddtionalRSAPrime "optional"
+}
+
+type pkcs1AddtionalRSAPrime struct {
+ Prime asn1.RawValue
+
+ // We ignore these values because rsa will calculate them.
+ Exp asn1.RawValue
+ Coeff asn1.RawValue
}
// rawValueIsInteger returns true iff the given ASN.1 RawValue is an INTEGER type.
@@ -46,6 +60,10 @@ func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err os.Error) {
return
}
+ if priv.Version > 1 {
+ return nil, os.ErrorString("x509: unsupported private key version")
+ }
+
if !rawValueIsInteger(&priv.N) ||
!rawValueIsInteger(&priv.D) ||
!rawValueIsInteger(&priv.P) ||
@@ -61,26 +79,66 @@ func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err os.Error) {
}
key.D = new(big.Int).SetBytes(priv.D.Bytes)
- key.P = new(big.Int).SetBytes(priv.P.Bytes)
- key.Q = new(big.Int).SetBytes(priv.Q.Bytes)
+ key.Primes = make([]*big.Int, 2+len(priv.AdditionalPrimes))
+ key.Primes[0] = new(big.Int).SetBytes(priv.P.Bytes)
+ key.Primes[1] = new(big.Int).SetBytes(priv.Q.Bytes)
+ for i, a := range priv.AdditionalPrimes {
+ if !rawValueIsInteger(&a.Prime) {
+ return nil, asn1.StructuralError{"tags don't match"}
+ }
+ key.Primes[i+2] = new(big.Int).SetBytes(a.Prime.Bytes)
+ // We ignore the other two values because rsa will calculate
+ // them as needed.
+ }
err = key.Validate()
if err != nil {
return nil, err
}
+ key.Precompute()
return
}
+// rawValueForBig returns an asn1.RawValue which represents the given integer.
+func rawValueForBig(n *big.Int) asn1.RawValue {
+ b := n.Bytes()
+ if n.Sign() >= 0 && len(b) > 0 && b[0]&0x80 != 0 {
+ // This positive number would be interpreted as a negative
+ // number in ASN.1 because the MSB is set.
+ padded := make([]byte, len(b)+1)
+ copy(padded[1:], b)
+ b = padded
+ }
+ return asn1.RawValue{Tag: 2, Bytes: b}
+}
+
// MarshalPKCS1PrivateKey converts a private key to ASN.1 DER encoded form.
func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte {
+ key.Precompute()
+
+ version := 0
+ if len(key.Primes) > 2 {
+ version = 1
+ }
+
priv := pkcs1PrivateKey{
- Version: 1,
- N: asn1.RawValue{Tag: 2, Bytes: key.PublicKey.N.Bytes()},
+ Version: version,
+ N: rawValueForBig(key.N),
E: key.PublicKey.E,
- D: asn1.RawValue{Tag: 2, Bytes: key.D.Bytes()},
- P: asn1.RawValue{Tag: 2, Bytes: key.P.Bytes()},
- Q: asn1.RawValue{Tag: 2, Bytes: key.Q.Bytes()},
+ D: rawValueForBig(key.D),
+ P: rawValueForBig(key.Primes[0]),
+ Q: rawValueForBig(key.Primes[1]),
+ Dp: rawValueForBig(key.Precomputed.Dp),
+ Dq: rawValueForBig(key.Precomputed.Dq),
+ Qinv: rawValueForBig(key.Precomputed.Qinv),
+ }
+
+ priv.AdditionalPrimes = make([]pkcs1AddtionalRSAPrime, len(key.Precomputed.CRTValues))
+ for i, values := range key.Precomputed.CRTValues {
+ priv.AdditionalPrimes[i].Prime = rawValueForBig(key.Primes[2+i])
+ priv.AdditionalPrimes[i].Exp = rawValueForBig(values.Exp)
+ priv.AdditionalPrimes[i].Coeff = rawValueForBig(values.Coeff)
}
b, _ := asn1.Marshal(priv)
@@ -90,6 +148,7 @@ func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte {
// These structures reflect the ASN.1 structure of X.509 certificates.:
type certificate struct {
+ Raw asn1.RawContent
TBSCertificate tbsCertificate
SignatureAlgorithm algorithmIdentifier
SignatureValue asn1.BitString
@@ -127,6 +186,7 @@ type validity struct {
}
type publicKeyInfo struct {
+ Raw asn1.RawContent
Algorithm algorithmIdentifier
PublicKey asn1.BitString
}
@@ -343,7 +403,10 @@ const (
// A Certificate represents an X.509 certificate.
type Certificate struct {
- Raw []byte // Raw ASN.1 DER contents.
+ Raw []byte // Complete ASN.1 DER content (certificate, signature algorithm and signature).
+ RawTBSCertificate []byte // Certificate part of raw ASN.1 DER content.
+ RawSubjectPublicKeyInfo []byte // DER encoded SubjectPublicKeyInfo.
+
Signature []byte
SignatureAlgorithm SignatureAlgorithm
@@ -395,6 +458,10 @@ func (ConstraintViolationError) String() string {
return "invalid signature: parent certificate cannot sign this kind of certificate"
}
+func (c *Certificate) Equal(other *Certificate) bool {
+ return bytes.Equal(c.Raw, other.Raw)
+}
+
// CheckSignatureFrom verifies that the signature on c is a valid signature
// from parent.
func (c *Certificate) CheckSignatureFrom(parent *Certificate) (err os.Error) {
@@ -434,69 +501,12 @@ func (c *Certificate) CheckSignatureFrom(parent *Certificate) (err os.Error) {
return UnsupportedAlgorithmError{}
}
- h.Write(c.Raw)
+ h.Write(c.RawTBSCertificate)
digest := h.Sum()
return rsa.VerifyPKCS1v15(pub, hashType, digest, c.Signature)
}
-func matchHostnames(pattern, host string) bool {
- if len(pattern) == 0 || len(host) == 0 {
- return false
- }
-
- patternParts := strings.Split(pattern, ".", -1)
- hostParts := strings.Split(host, ".", -1)
-
- if len(patternParts) != len(hostParts) {
- return false
- }
-
- for i, patternPart := range patternParts {
- if patternPart == "*" {
- continue
- }
- if patternPart != hostParts[i] {
- return false
- }
- }
-
- return true
-}
-
-type HostnameError struct {
- Certificate *Certificate
- Host string
-}
-
-func (h *HostnameError) String() string {
- var valid string
- c := h.Certificate
- if len(c.DNSNames) > 0 {
- valid = strings.Join(c.DNSNames, ", ")
- } else {
- valid = c.Subject.CommonName
- }
- return "certificate is valid for " + valid + ", not " + h.Host
-}
-
-// VerifyHostname returns nil if c is a valid certificate for the named host.
-// Otherwise it returns an os.Error describing the mismatch.
-func (c *Certificate) VerifyHostname(h string) os.Error {
- if len(c.DNSNames) > 0 {
- for _, match := range c.DNSNames {
- if matchHostnames(match, h) {
- return nil
- }
- }
- // If Subject Alt Name is given, we ignore the common name.
- } else if matchHostnames(c.Subject.CommonName, h) {
- return nil
- }
-
- return &HostnameError{c, h}
-}
-
type UnhandledCriticalExtension struct{}
func (h UnhandledCriticalExtension) String() string {
@@ -558,7 +568,9 @@ func parsePublicKey(algo PublicKeyAlgorithm, asn1Data []byte) (interface{}, os.E
func parseCertificate(in *certificate) (*Certificate, os.Error) {
out := new(Certificate)
- out.Raw = in.TBSCertificate.Raw
+ out.Raw = in.Raw
+ out.RawTBSCertificate = in.TBSCertificate.Raw
+ out.RawSubjectPublicKeyInfo = in.TBSCertificate.PublicKey.Raw
out.Signature = in.SignatureValue.RightAlign()
out.SignatureAlgorithm =
@@ -975,7 +987,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub *rsa.P
Issuer: parent.Subject.toRDNSequence(),
Validity: validity{template.NotBefore, template.NotAfter},
Subject: template.Subject.toRDNSequence(),
- PublicKey: publicKeyInfo{algorithmIdentifier{oidRSA}, encodedPublicKey},
+ PublicKey: publicKeyInfo{nil, algorithmIdentifier{oidRSA}, encodedPublicKey},
Extensions: extensions,
}
@@ -996,6 +1008,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub *rsa.P
}
cert, err = asn1.Marshal(certificate{
+ nil,
c,
algorithmIdentifier{oidSHA1WithRSA},
asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
diff --git a/libgo/go/crypto/x509/x509_test.go b/libgo/go/crypto/x509/x509_test.go
index d9511b8..a42113a 100644
--- a/libgo/go/crypto/x509/x509_test.go
+++ b/libgo/go/crypto/x509/x509_test.go
@@ -20,12 +20,13 @@ func TestParsePKCS1PrivateKey(t *testing.T) {
priv, err := ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
t.Errorf("Failed to parse private key: %s", err)
+ return
}
if priv.PublicKey.N.Cmp(rsaPrivateKey.PublicKey.N) != 0 ||
priv.PublicKey.E != rsaPrivateKey.PublicKey.E ||
priv.D.Cmp(rsaPrivateKey.D) != 0 ||
- priv.P.Cmp(rsaPrivateKey.P) != 0 ||
- priv.Q.Cmp(rsaPrivateKey.Q) != 0 {
+ priv.Primes[0].Cmp(rsaPrivateKey.Primes[0]) != 0 ||
+ priv.Primes[1].Cmp(rsaPrivateKey.Primes[1]) != 0 {
t.Errorf("got:%+v want:%+v", priv, rsaPrivateKey)
}
}
@@ -47,14 +48,54 @@ func bigFromString(s string) *big.Int {
return ret
}
+func fromBase10(base10 string) *big.Int {
+ i := new(big.Int)
+ i.SetString(base10, 10)
+ return i
+}
+
var rsaPrivateKey = &rsa.PrivateKey{
PublicKey: rsa.PublicKey{
N: bigFromString("9353930466774385905609975137998169297361893554149986716853295022578535724979677252958524466350471210367835187480748268864277464700638583474144061408845077"),
E: 65537,
},
D: bigFromString("7266398431328116344057699379749222532279343923819063639497049039389899328538543087657733766554155839834519529439851673014800261285757759040931985506583861"),
- P: bigFromString("98920366548084643601728869055592650835572950932266967461790948584315647051443"),
- Q: bigFromString("94560208308847015747498523884063394671606671904944666360068158221458669711639"),
+ Primes: []*big.Int{
+ bigFromString("98920366548084643601728869055592650835572950932266967461790948584315647051443"),
+ bigFromString("94560208308847015747498523884063394671606671904944666360068158221458669711639"),
+ },
+}
+
+func TestMarshalRSAPrivateKey(t *testing.T) {
+ priv := &rsa.PrivateKey{
+ PublicKey: rsa.PublicKey{
+ N: fromBase10("16346378922382193400538269749936049106320265317511766357599732575277382844051791096569333808598921852351577762718529818072849191122419410612033592401403764925096136759934497687765453905884149505175426053037420486697072448609022753683683718057795566811401938833367954642951433473337066311978821180526439641496973296037000052546108507805269279414789035461158073156772151892452251106173507240488993608650881929629163465099476849643165682709047462010581308719577053905787496296934240246311806555924593059995202856826239801816771116902778517096212527979497399966526283516447337775509777558018145573127308919204297111496233"),
+ E: 3,
+ },
+ D: fromBase10("10897585948254795600358846499957366070880176878341177571733155050184921896034527397712889205732614568234385175145686545381899460748279607074689061600935843283397424506622998458510302603922766336783617368686090042765718290914099334449154829375179958369993407724946186243249568928237086215759259909861748642124071874879861299389874230489928271621259294894142840428407196932444474088857746123104978617098858619445675532587787023228852383149557470077802718705420275739737958953794088728369933811184572620857678792001136676902250566845618813972833750098806496641114644760255910789397593428910198080271317419213080834885003"),
+ Primes: []*big.Int{
+ fromBase10("1025363189502892836833747188838978207017355117492483312747347695538428729137306368764177201532277413433182799108299960196606011786562992097313508180436744488171474690412562218914213688661311117337381958560443"),
+ fromBase10("3467903426626310123395340254094941045497208049900750380025518552334536945536837294961497712862519984786362199788654739924501424784631315081391467293694361474867825728031147665777546570788493758372218019373"),
+ fromBase10("4597024781409332673052708605078359346966325141767460991205742124888960305710298765592730135879076084498363772408626791576005136245060321874472727132746643162385746062759369754202494417496879741537284589047"),
+ },
+ }
+
+ derBytes := MarshalPKCS1PrivateKey(priv)
+
+ priv2, err := ParsePKCS1PrivateKey(derBytes)
+ if err != nil {
+ t.Errorf("error parsing serialized key: %s", err)
+ return
+ }
+ if priv.PublicKey.N.Cmp(priv2.PublicKey.N) != 0 ||
+ priv.PublicKey.E != priv2.PublicKey.E ||
+ priv.D.Cmp(priv2.D) != 0 ||
+ len(priv2.Primes) != 3 ||
+ priv.Primes[0].Cmp(priv2.Primes[0]) != 0 ||
+ priv.Primes[1].Cmp(priv2.Primes[1]) != 0 ||
+ priv.Primes[2].Cmp(priv2.Primes[2]) != 0 {
+ t.Errorf("got:%+v want:%+v", priv, priv2)
+ }
}
type matchHostnamesTest struct {
diff --git a/libgo/go/crypto/xtea/cipher.go b/libgo/go/crypto/xtea/cipher.go
index b0fa2a1..f2a5da0 100644
--- a/libgo/go/crypto/xtea/cipher.go
+++ b/libgo/go/crypto/xtea/cipher.go
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// This package implements XTEA encryption, as defined in Needham and
-// Wheeler's 1997 technical report, "Tea extensions."
+// Package xtea implements XTEA encryption, as defined in Needham and Wheeler's
+// 1997 technical report, "Tea extensions."
package xtea
// For details, see http://www.cix.co.uk/~klockstone/xtea.pdf