summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel Russell <gabriel.russell@mongodb.com>2016-03-24 17:43:11 -0400
committerGabriel Russell <gabriel.russell@mongodb.com>2016-03-24 17:43:11 -0400
commitc9a4d131a998a1f396764402cd6e2dd377c2c095 (patch)
treef8791012d03dfaa6e98d389fb72f568ecd318e36
parent7bf0f42169ab581d25f1237b069c3266788332ca (diff)
downloadmongo-osx-3.2-ssl.tar.gz
TOOLS-1100 revendor spacemonkeygo/opensslosx-3.2-ssl
-rw-r--r--Godeps2
-rw-r--r--vendor/src/github.com/spacemonkeygo/openssl/build.go1
-rw-r--r--vendor/src/github.com/spacemonkeygo/openssl/cert.go407
-rw-r--r--vendor/src/github.com/spacemonkeygo/openssl/cert_test.go139
-rw-r--r--vendor/src/github.com/spacemonkeygo/openssl/ciphers.go16
-rw-r--r--vendor/src/github.com/spacemonkeygo/openssl/ciphers_test.go54
-rw-r--r--vendor/src/github.com/spacemonkeygo/openssl/conn.go141
-rw-r--r--vendor/src/github.com/spacemonkeygo/openssl/ctx.go158
-rw-r--r--vendor/src/github.com/spacemonkeygo/openssl/ctx_test.go48
-rw-r--r--vendor/src/github.com/spacemonkeygo/openssl/dhparam.go65
-rw-r--r--vendor/src/github.com/spacemonkeygo/openssl/digest.go53
-rw-r--r--vendor/src/github.com/spacemonkeygo/openssl/key.go374
-rw-r--r--vendor/src/github.com/spacemonkeygo/openssl/key_test.go (renamed from vendor/src/github.com/spacemonkeygo/openssl/pem_test.go)15
-rw-r--r--vendor/src/github.com/spacemonkeygo/openssl/net.go19
-rw-r--r--vendor/src/github.com/spacemonkeygo/openssl/nid.go199
-rw-r--r--vendor/src/github.com/spacemonkeygo/openssl/pem.go380
-rw-r--r--vendor/src/github.com/spacemonkeygo/openssl/sni.c23
-rw-r--r--vendor/src/github.com/spacemonkeygo/openssl/sni_test.go23
-rw-r--r--vendor/src/github.com/spacemonkeygo/openssl/ssl.go167
-rw-r--r--vendor/src/github.com/spacemonkeygo/openssl/verify.c10
20 files changed, 1900 insertions, 394 deletions
diff --git a/Godeps b/Godeps
index f714cd16725..2c209cace9a 100644
--- a/Godeps
+++ b/Godeps
@@ -4,6 +4,6 @@ github.com/jacobsa/oglematchers 3ecefc49db07722beca986d9bb71ddd026b133f0
github.com/smartystreets/goconvey 995f5b2e021c69b8b028ba6d0b05c1dd500783db
github.com/jessevdk/go-flags 5e118789801496c93ba210d34ef1f2ce5a9173bd
github.com/3rf/mongo-lint f6cf4f8a7d07167375b035d186a1e8b3ebf28aa3
-github.com/spacemonkeygo/openssl 4c6dbafa5ec35b3ffc6a1b1e1fe29c3eba2053ec github.com/10gen/openssl
+github.com/spacemonkeygo/openssl 28e108cf76dcb7bd5aa445a0f4348b312464004e github.com/10gen/openssl
github.com/howeyc/gopass 2c70fa70727c953c51695f800f25d6b44abb368e
golang.org/x/crypto c57d4a71915a248dbad846d60825145062b4c18e
diff --git a/vendor/src/github.com/spacemonkeygo/openssl/build.go b/vendor/src/github.com/spacemonkeygo/openssl/build.go
index e24a0c8db63..dd72651d3ea 100644
--- a/vendor/src/github.com/spacemonkeygo/openssl/build.go
+++ b/vendor/src/github.com/spacemonkeygo/openssl/build.go
@@ -18,5 +18,6 @@ package openssl
// #cgo linux pkg-config: openssl
// #cgo windows CFLAGS: -DWIN32_LEAN_AND_MEAN
+// #cgo darwin CFLAGS: -Wno-deprecated-declarations
// #cgo darwin LDFLAGS: -lssl -lcrypto
import "C"
diff --git a/vendor/src/github.com/spacemonkeygo/openssl/cert.go b/vendor/src/github.com/spacemonkeygo/openssl/cert.go
new file mode 100644
index 00000000000..61637c649fa
--- /dev/null
+++ b/vendor/src/github.com/spacemonkeygo/openssl/cert.go
@@ -0,0 +1,407 @@
+// Copyright (C) 2014 Space Monkey, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build cgo
+
+package openssl
+
+// #include <openssl/conf.h>
+// #include <openssl/ssl.h>
+// #include <openssl/x509v3.h>
+//
+// void OPENSSL_free_not_a_macro(void *ref) { OPENSSL_free(ref); }
+//
+import "C"
+
+import (
+ "errors"
+ "io/ioutil"
+ "math/big"
+ "runtime"
+ "time"
+ "unsafe"
+)
+
+type EVP_MD int
+
+const (
+ EVP_NULL EVP_MD = iota
+ EVP_MD5 EVP_MD = iota
+ EVP_SHA EVP_MD = iota
+ EVP_SHA1 EVP_MD = iota
+ EVP_DSS EVP_MD = iota
+ EVP_DSS1 EVP_MD = iota
+ EVP_MDC2 EVP_MD = iota
+ EVP_RIPEMD160 EVP_MD = iota
+ EVP_SHA224 EVP_MD = iota
+ EVP_SHA256 EVP_MD = iota
+ EVP_SHA384 EVP_MD = iota
+ EVP_SHA512 EVP_MD = iota
+)
+
+type Certificate struct {
+ x *C.X509
+ Issuer *Certificate
+ ref interface{}
+ pubKey PublicKey
+}
+
+type CertificateInfo struct {
+ Serial *big.Int
+ Issued time.Duration
+ Expires time.Duration
+ Country string
+ Organization string
+ CommonName string
+}
+
+type Name struct {
+ name *C.X509_NAME
+}
+
+// Allocate and return a new Name object.
+func NewName() (*Name, error) {
+ n := C.X509_NAME_new()
+ if n == nil {
+ return nil, errors.New("could not create x509 name")
+ }
+ name := &Name{name: n}
+ runtime.SetFinalizer(name, func(n *Name) {
+ C.X509_NAME_free(n.name)
+ })
+ return name, nil
+}
+
+// AddTextEntry appends a text entry to an X509 NAME.
+func (n *Name) AddTextEntry(field, value string) error {
+ cfield := C.CString(field)
+ defer C.free(unsafe.Pointer(cfield))
+ cvalue := (*C.uchar)(unsafe.Pointer(C.CString(value)))
+ defer C.free(unsafe.Pointer(cvalue))
+ ret := C.X509_NAME_add_entry_by_txt(
+ n.name, cfield, C.MBSTRING_ASC, cvalue, -1, -1, 0)
+ if ret != 1 {
+ return errors.New("failed to add x509 name text entry")
+ }
+ return nil
+}
+
+// AddTextEntries allows adding multiple entries to a name in one call.
+func (n *Name) AddTextEntries(entries map[string]string) error {
+ for f, v := range entries {
+ if err := n.AddTextEntry(f, v); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// GetEntry returns a name entry based on NID. If no entry, then ("", false) is
+// returned.
+func (n *Name) GetEntry(nid NID) (entry string, ok bool) {
+ entrylen := C.X509_NAME_get_text_by_NID(n.name, C.int(nid), nil, 0)
+ if entrylen == -1 {
+ return "", false
+ }
+ buf := (*C.char)(C.malloc(C.size_t(entrylen + 1)))
+ defer C.free(unsafe.Pointer(buf))
+ C.X509_NAME_get_text_by_NID(n.name, C.int(nid), buf, entrylen+1)
+ return C.GoStringN(buf, entrylen), true
+}
+
+// NewCertificate generates a basic certificate based
+// on the provided CertificateInfo struct
+func NewCertificate(info *CertificateInfo, key PublicKey) (*Certificate, error) {
+ c := &Certificate{x: C.X509_new()}
+ runtime.SetFinalizer(c, func(c *Certificate) {
+ C.X509_free(c.x)
+ })
+
+ name, err := c.GetSubjectName()
+ if err != nil {
+ return nil, err
+ }
+ err = name.AddTextEntries(map[string]string{
+ "C": info.Country,
+ "O": info.Organization,
+ "CN": info.CommonName,
+ })
+ if err != nil {
+ return nil, err
+ }
+ // self-issue for now
+ if err := c.SetIssuerName(name); err != nil {
+ return nil, err
+ }
+ if err := c.SetSerial(info.Serial); err != nil {
+ return nil, err
+ }
+ if err := c.SetIssueDate(info.Issued); err != nil {
+ return nil, err
+ }
+ if err := c.SetExpireDate(info.Expires); err != nil {
+ return nil, err
+ }
+ if err := c.SetPubKey(key); err != nil {
+ return nil, err
+ }
+ return c, nil
+}
+
+func (c *Certificate) GetSubjectName() (*Name, error) {
+ n := C.X509_get_subject_name(c.x)
+ if n == nil {
+ return nil, errors.New("failed to get subject name")
+ }
+ return &Name{name: n}, nil
+}
+
+func (c *Certificate) GetIssuerName() (*Name, error) {
+ n := C.X509_get_issuer_name(c.x)
+ if n == nil {
+ return nil, errors.New("failed to get issuer name")
+ }
+ return &Name{name: n}, nil
+}
+
+func (c *Certificate) SetSubjectName(name *Name) error {
+ if C.X509_set_subject_name(c.x, name.name) != 1 {
+ return errors.New("failed to set subject name")
+ }
+ return nil
+}
+
+// SetIssuer updates the stored Issuer cert
+// and the internal x509 Issuer Name of a certificate.
+// The stored Issuer reference is used when adding extensions.
+func (c *Certificate) SetIssuer(issuer *Certificate) error {
+ name, err := issuer.GetSubjectName()
+ if err != nil {
+ return err
+ }
+ if err = c.SetIssuerName(name); err != nil {
+ return err
+ }
+ c.Issuer = issuer
+ return nil
+}
+
+// SetIssuerName populates the issuer name of a certificate.
+// Use SetIssuer instead, if possible.
+func (c *Certificate) SetIssuerName(name *Name) error {
+ if C.X509_set_issuer_name(c.x, name.name) != 1 {
+ return errors.New("failed to set subject name")
+ }
+ return nil
+}
+
+// SetSerial sets the serial of a certificate.
+func (c *Certificate) SetSerial(serial *big.Int) error {
+ sno := C.ASN1_INTEGER_new()
+ defer C.ASN1_INTEGER_free(sno)
+ bn := C.BN_new()
+ defer C.BN_free(bn)
+
+ serialBytes := serial.Bytes()
+ if bn = C.BN_bin2bn((*C.uchar)(unsafe.Pointer(&serialBytes[0])), C.int(len(serialBytes)), bn); bn == nil {
+ return errors.New("failed to set serial")
+ }
+ if sno = C.BN_to_ASN1_INTEGER(bn, sno); sno == nil {
+ return errors.New("failed to set serial")
+ }
+ if C.X509_set_serialNumber(c.x, sno) != 1 {
+ return errors.New("failed to set serial")
+ }
+ return nil
+}
+
+// SetIssueDate sets the certificate issue date relative to the current time.
+func (c *Certificate) SetIssueDate(when time.Duration) error {
+ offset := C.long(when / time.Second)
+ result := C.X509_gmtime_adj(c.x.cert_info.validity.notBefore, offset)
+ if result == nil {
+ return errors.New("failed to set issue date")
+ }
+ return nil
+}
+
+// SetExpireDate sets the certificate issue date relative to the current time.
+func (c *Certificate) SetExpireDate(when time.Duration) error {
+ offset := C.long(when / time.Second)
+ result := C.X509_gmtime_adj(c.x.cert_info.validity.notAfter, offset)
+ if result == nil {
+ return errors.New("failed to set expire date")
+ }
+ return nil
+}
+
+// SetPubKey assigns a new public key to a certificate.
+func (c *Certificate) SetPubKey(pubKey PublicKey) error {
+ c.pubKey = pubKey
+ if C.X509_set_pubkey(c.x, pubKey.evpPKey()) != 1 {
+ return errors.New("failed to set public key")
+ }
+ return nil
+}
+
+// Sign a certificate using a private key and a digest name.
+// Accepted digest names are 'sha256', 'sha384', and 'sha512'.
+func (c *Certificate) Sign(privKey PrivateKey, digest EVP_MD) error {
+ switch digest {
+ case EVP_SHA256:
+ case EVP_SHA384:
+ case EVP_SHA512:
+ default:
+ return errors.New("Unsupported digest" +
+ "You're probably looking for 'EVP_SHA256' or 'EVP_SHA512'.")
+ }
+ return c.insecureSign(privKey, digest)
+}
+
+func (c *Certificate) insecureSign(privKey PrivateKey, digest EVP_MD) error {
+ var md *C.EVP_MD
+ switch digest {
+ // please don't use these digest functions
+ case EVP_NULL:
+ md = C.EVP_md_null()
+ case EVP_MD5:
+ md = C.EVP_md5()
+ case EVP_SHA:
+ md = C.EVP_sha()
+ case EVP_SHA1:
+ md = C.EVP_sha1()
+ case EVP_DSS:
+ md = C.EVP_dss()
+ case EVP_DSS1:
+ md = C.EVP_dss1()
+ case EVP_RIPEMD160:
+ md = C.EVP_ripemd160()
+ case EVP_SHA224:
+ md = C.EVP_sha224()
+ // you actually want one of these
+ case EVP_SHA256:
+ md = C.EVP_sha256()
+ case EVP_SHA384:
+ md = C.EVP_sha384()
+ case EVP_SHA512:
+ md = C.EVP_sha512()
+ }
+ if C.X509_sign(c.x, privKey.evpPKey(), md) <= 0 {
+ return errors.New("failed to sign certificate")
+ }
+ return nil
+}
+
+// Add an extension to a certificate.
+// Extension constants are NID_* as found in openssl.
+func (c *Certificate) AddExtension(nid NID, value string) error {
+ issuer := c
+ if c.Issuer != nil {
+ issuer = c.Issuer
+ }
+ var ctx C.X509V3_CTX
+ C.X509V3_set_ctx(&ctx, c.x, issuer.x, nil, nil, 0)
+ ex := C.X509V3_EXT_conf_nid(nil, &ctx, C.int(nid), C.CString(value))
+ if ex == nil {
+ return errors.New("failed to create x509v3 extension")
+ }
+ defer C.X509_EXTENSION_free(ex)
+ if C.X509_add_ext(c.x, ex, -1) <= 0 {
+ return errors.New("failed to add x509v3 extension")
+ }
+ return nil
+}
+
+// Wraps AddExtension using a map of NID to text extension.
+// Will return without finishing if it encounters an error.
+func (c *Certificate) AddExtensions(extensions map[NID]string) error {
+ for nid, value := range extensions {
+ if err := c.AddExtension(nid, value); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// LoadCertificateFromPEM loads an X509 certificate from a PEM-encoded block.
+func LoadCertificateFromPEM(pem_block []byte) (*Certificate, error) {
+ if len(pem_block) == 0 {
+ return nil, errors.New("empty pem block")
+ }
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+ bio := C.BIO_new_mem_buf(unsafe.Pointer(&pem_block[0]),
+ C.int(len(pem_block)))
+ cert := C.PEM_read_bio_X509(bio, nil, nil, nil)
+ C.BIO_free(bio)
+ if cert == nil {
+ return nil, errorFromErrorQueue()
+ }
+ x := &Certificate{x: cert}
+ runtime.SetFinalizer(x, func(x *Certificate) {
+ C.X509_free(x.x)
+ })
+ return x, nil
+}
+
+// MarshalPEM converts the X509 certificate to PEM-encoded format
+func (c *Certificate) MarshalPEM() (pem_block []byte, err error) {
+ bio := C.BIO_new(C.BIO_s_mem())
+ if bio == nil {
+ return nil, errors.New("failed to allocate memory BIO")
+ }
+ defer C.BIO_free(bio)
+ if int(C.PEM_write_bio_X509(bio, c.x)) != 1 {
+ return nil, errors.New("failed dumping certificate")
+ }
+ return ioutil.ReadAll(asAnyBio(bio))
+}
+
+// PublicKey returns the public key embedded in the X509 certificate.
+func (c *Certificate) PublicKey() (PublicKey, error) {
+ pkey := C.X509_get_pubkey(c.x)
+ if pkey == nil {
+ return nil, errors.New("no public key found")
+ }
+ key := &pKey{key: pkey}
+ runtime.SetFinalizer(key, func(key *pKey) {
+ C.EVP_PKEY_free(key.key)
+ })
+ return key, nil
+}
+
+// GetSerialNumberHex returns the certificate's serial number in hex format
+func (c *Certificate) GetSerialNumberHex() (serial string) {
+ asn1_i := C.X509_get_serialNumber(c.x)
+ bignum := C.ASN1_INTEGER_to_BN(asn1_i, nil)
+ hex := C.BN_bn2hex(bignum)
+ serial = C.GoString(hex)
+ C.BN_free(bignum)
+ C.OPENSSL_free_not_a_macro(unsafe.Pointer(hex))
+ return
+}
+
+func (c *Certificate) X509NamePrintEx() (out []byte, err error) {
+ bio := C.BIO_new(C.BIO_s_mem())
+ if bio == nil {
+ return nil, errors.New("failed to allocate memory BIO")
+ }
+ defer C.BIO_free(bio)
+ name := C.X509_get_subject_name(c.x)
+ // TODO, pass in flags instead of using this hardcoded one
+ if int(C.X509_NAME_print_ex(bio, name, 0, C.XN_FLAG_RFC2253)) < 0 {
+ return nil, errors.New("failed formatting subject")
+ }
+ return ioutil.ReadAll(asAnyBio(bio))
+}
diff --git a/vendor/src/github.com/spacemonkeygo/openssl/cert_test.go b/vendor/src/github.com/spacemonkeygo/openssl/cert_test.go
new file mode 100644
index 00000000000..c32883ba4eb
--- /dev/null
+++ b/vendor/src/github.com/spacemonkeygo/openssl/cert_test.go
@@ -0,0 +1,139 @@
+// Copyright (C) 2014 Ryan Hileman
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package openssl
+
+import (
+ "math/big"
+ "testing"
+ "time"
+)
+
+func TestCertGenerate(t *testing.T) {
+ key, err := GenerateRSAKey(2048)
+ if err != nil {
+ t.Fatal(err)
+ }
+ info := &CertificateInfo{
+ Serial: big.NewInt(int64(1)),
+ Issued: 0,
+ Expires: 24 * time.Hour,
+ Country: "US",
+ Organization: "Test",
+ CommonName: "localhost",
+ }
+ cert, err := NewCertificate(info, key)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := cert.Sign(key, EVP_SHA256); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestCAGenerate(t *testing.T) {
+ cakey, err := GenerateRSAKey(2048)
+ if err != nil {
+ t.Fatal(err)
+ }
+ info := &CertificateInfo{
+ Serial: big.NewInt(int64(1)),
+ Issued: 0,
+ Expires: 24 * time.Hour,
+ Country: "US",
+ Organization: "Test CA",
+ CommonName: "CA",
+ }
+ ca, err := NewCertificate(info, cakey)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := ca.AddExtensions(map[NID]string{
+ NID_basic_constraints: "critical,CA:TRUE",
+ NID_key_usage: "critical,keyCertSign,cRLSign",
+ NID_subject_key_identifier: "hash",
+ NID_netscape_cert_type: "sslCA",
+ }); err != nil {
+ t.Fatal(err)
+ }
+ if err := ca.Sign(cakey, EVP_SHA256); err != nil {
+ t.Fatal(err)
+ }
+ key, err := GenerateRSAKey(2048)
+ if err != nil {
+ t.Fatal(err)
+ }
+ info = &CertificateInfo{
+ Serial: big.NewInt(int64(1)),
+ Issued: 0,
+ Expires: 24 * time.Hour,
+ Country: "US",
+ Organization: "Test",
+ CommonName: "localhost",
+ }
+ cert, err := NewCertificate(info, key)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := cert.AddExtensions(map[NID]string{
+ NID_basic_constraints: "critical,CA:FALSE",
+ NID_key_usage: "keyEncipherment",
+ NID_ext_key_usage: "serverAuth",
+ }); err != nil {
+ t.Fatal(err)
+ }
+ if err := cert.SetIssuer(ca); err != nil {
+ t.Fatal(err)
+ }
+ if err := cert.Sign(cakey, EVP_SHA256); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestCertGetNameEntry(t *testing.T) {
+ key, err := GenerateRSAKey(2048)
+ if err != nil {
+ t.Fatal(err)
+ }
+ info := &CertificateInfo{
+ Serial: big.NewInt(int64(1)),
+ Issued: 0,
+ Expires: 24 * time.Hour,
+ Country: "US",
+ Organization: "Test",
+ CommonName: "localhost",
+ }
+ cert, err := NewCertificate(info, key)
+ if err != nil {
+ t.Fatal(err)
+ }
+ name, err := cert.GetSubjectName()
+ if err != nil {
+ t.Fatal(err)
+ }
+ entry, ok := name.GetEntry(NID_commonName)
+ if !ok {
+ t.Fatal("no common name")
+ }
+ if entry != "localhost" {
+ t.Fatalf("expected localhost; got %q", entry)
+ }
+ entry, ok = name.GetEntry(NID_localityName)
+ if ok {
+ t.Fatal("did not expect a locality name")
+ }
+ if entry != "" {
+ t.Fatalf("entry should be empty; got %q", entry)
+ }
+}
diff --git a/vendor/src/github.com/spacemonkeygo/openssl/ciphers.go b/vendor/src/github.com/spacemonkeygo/openssl/ciphers.go
index 46ea4ced708..12662707f54 100644
--- a/vendor/src/github.com/spacemonkeygo/openssl/ciphers.go
+++ b/vendor/src/github.com/spacemonkeygo/openssl/ciphers.go
@@ -73,8 +73,8 @@ type Cipher struct {
ptr *C.EVP_CIPHER
}
-func (c *Cipher) Nid() int {
- return int(C.EVP_CIPHER_nid_not_a_macro(c.ptr))
+func (c *Cipher) Nid() NID {
+ return NID(C.EVP_CIPHER_nid_not_a_macro(c.ptr))
}
func (c *Cipher) ShortName() (string, error) {
@@ -93,7 +93,7 @@ func (c *Cipher) IVSize() int {
return int(C.EVP_CIPHER_iv_length_not_a_macro(c.ptr))
}
-func Nid2ShortName(nid int) (string, error) {
+func Nid2ShortName(nid NID) (string, error) {
sn := C.OBJ_nid2sn(C.int(nid))
if sn == nil {
return "", fmt.Errorf("NID %d not found", nid)
@@ -112,7 +112,7 @@ func GetCipherByName(name string) (*Cipher, error) {
return &Cipher{ptr: p}, nil
}
-func GetCipherByNid(nid int) (*Cipher, error) {
+func GetCipherByNid(nid NID) (*Cipher, error) {
sn, err := Nid2ShortName(nid)
if err != nil {
return nil, err
@@ -153,7 +153,13 @@ func (ctx *cipherCtx) applyKeyAndIV(key, iv []byte) error {
iptr = (*C.uchar)(&iv[0])
}
if kptr != nil || iptr != nil {
- if 1 != C.EVP_EncryptInit_ex(ctx.ctx, nil, nil, kptr, iptr) {
+ var res C.int
+ if ctx.ctx.encrypt != 0 {
+ res = C.EVP_EncryptInit_ex(ctx.ctx, nil, nil, kptr, iptr)
+ } else {
+ res = C.EVP_DecryptInit_ex(ctx.ctx, nil, nil, kptr, iptr)
+ }
+ if 1 != res {
return errors.New("failed to apply key/IV")
}
}
diff --git a/vendor/src/github.com/spacemonkeygo/openssl/ciphers_test.go b/vendor/src/github.com/spacemonkeygo/openssl/ciphers_test.go
index b0707dff1e9..d1d430b1e15 100644
--- a/vendor/src/github.com/spacemonkeygo/openssl/ciphers_test.go
+++ b/vendor/src/github.com/spacemonkeygo/openssl/ciphers_test.go
@@ -251,3 +251,57 @@ func TestBadAAD(t *testing.T) {
}
checkEqual(t, plaintext_out, plaintext)
}
+
+func TestNonAuthenticatedEncryption(t *testing.T) {
+ key := []byte("never gonna give you up, never g")
+ iv := []byte("onna let you dow")
+ plaintext1 := "n, never gonna run around"
+ plaintext2 := " and desert you"
+
+ cipher, err := GetCipherByName("aes-256-cbc")
+ if err != nil {
+ t.Fatal("Could not get cipher: ", err)
+ }
+
+ eCtx, err := NewEncryptionCipherCtx(cipher, nil, key, iv)
+ if err != nil {
+ t.Fatal("Could not create encryption context: ", err)
+ }
+ cipherbytes, err := eCtx.EncryptUpdate([]byte(plaintext1))
+ if err != nil {
+ t.Fatal("EncryptUpdate(plaintext1) failure: ", err)
+ }
+ ciphertext := string(cipherbytes)
+ cipherbytes, err = eCtx.EncryptUpdate([]byte(plaintext2))
+ if err != nil {
+ t.Fatal("EncryptUpdate(plaintext2) failure: ", err)
+ }
+ ciphertext += string(cipherbytes)
+ cipherbytes, err = eCtx.EncryptFinal()
+ if err != nil {
+ t.Fatal("EncryptFinal() failure: ", err)
+ }
+ ciphertext += string(cipherbytes)
+
+ dCtx, err := NewDecryptionCipherCtx(cipher, nil, key, iv)
+ if err != nil {
+ t.Fatal("Could not create decryption context: ", err)
+ }
+ plainbytes, err := dCtx.DecryptUpdate([]byte(ciphertext[:15]))
+ if err != nil {
+ t.Fatal("DecryptUpdate(ciphertext part 1) failure: ", err)
+ }
+ plainOutput := string(plainbytes)
+ plainbytes, err = dCtx.DecryptUpdate([]byte(ciphertext[15:]))
+ if err != nil {
+ t.Fatal("DecryptUpdate(ciphertext part 2) failure: ", err)
+ }
+ plainOutput += string(plainbytes)
+ plainbytes, err = dCtx.DecryptFinal()
+ if err != nil {
+ t.Fatal("DecryptFinal() failure: ", err)
+ }
+ plainOutput += string(plainbytes)
+
+ checkEqual(t, []byte(plainOutput), plaintext1+plaintext2)
+}
diff --git a/vendor/src/github.com/spacemonkeygo/openssl/conn.go b/vendor/src/github.com/spacemonkeygo/openssl/conn.go
index 4049a021801..afc73a50ae3 100644
--- a/vendor/src/github.com/spacemonkeygo/openssl/conn.go
+++ b/vendor/src/github.com/spacemonkeygo/openssl/conn.go
@@ -16,19 +16,28 @@
package openssl
-// #include <stdlib.h>
-// #include <openssl/ssl.h>
-// #include <openssl/conf.h>
-// #include <openssl/err.h>
-//
-// int sk_X509_num_not_a_macro(STACK_OF(X509) *sk) { return sk_X509_num(sk); }
-// X509 *sk_X509_value_not_a_macro(STACK_OF(X509)* sk, int i) {
-// return sk_X509_value(sk, i);
-// }
+/*
+#include <stdlib.h>
+#include <openssl/ssl.h>
+#include <openssl/conf.h>
+#include <openssl/err.h>
+
+int sk_X509_num_not_a_macro(STACK_OF(X509) *sk) { return sk_X509_num(sk); }
+X509 *sk_X509_value_not_a_macro(STACK_OF(X509)* sk, int i) {
+ return sk_X509_value(sk, i);
+}
+const char * SSL_get_cipher_name_not_a_macro(const SSL *ssl) {
+ return SSL_get_cipher_name(ssl);
+}
+static int SSL_session_reused_not_a_macro(SSL *ssl) {
+ return SSL_session_reused(ssl);
+}
+*/
import "C"
import (
"errors"
+ "fmt"
"io"
"net"
"runtime"
@@ -57,6 +66,56 @@ type Conn struct {
want_read_future *utils.Future
}
+type VerifyResult int
+
+const (
+ Ok VerifyResult = C.X509_V_OK
+ UnableToGetIssuerCert VerifyResult = C.X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT
+ UnableToGetCrl VerifyResult = C.X509_V_ERR_UNABLE_TO_GET_CRL
+ UnableToDecryptCertSignature VerifyResult = C.X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE
+ UnableToDecryptCrlSignature VerifyResult = C.X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE
+ UnableToDecodeIssuerPublicKey VerifyResult = C.X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY
+ CertSignatureFailure VerifyResult = C.X509_V_ERR_CERT_SIGNATURE_FAILURE
+ CrlSignatureFailure VerifyResult = C.X509_V_ERR_CRL_SIGNATURE_FAILURE
+ CertNotYetValid VerifyResult = C.X509_V_ERR_CERT_NOT_YET_VALID
+ CertHasExpired VerifyResult = C.X509_V_ERR_CERT_HAS_EXPIRED
+ CrlNotYetValid VerifyResult = C.X509_V_ERR_CRL_NOT_YET_VALID
+ CrlHasExpired VerifyResult = C.X509_V_ERR_CRL_HAS_EXPIRED
+ ErrorInCertNotBeforeField VerifyResult = C.X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD
+ ErrorInCertNotAfterField VerifyResult = C.X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD
+ ErrorInCrlLastUpdateField VerifyResult = C.X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD
+ ErrorInCrlNextUpdateField VerifyResult = C.X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD
+ OutOfMem VerifyResult = C.X509_V_ERR_OUT_OF_MEM
+ DepthZeroSelfSignedCert VerifyResult = C.X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
+ SelfSignedCertInChain VerifyResult = C.X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
+ UnableToGetIssuerCertLocally VerifyResult = C.X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
+ UnableToVerifyLeafSignature VerifyResult = C.X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE
+ CertChainTooLong VerifyResult = C.X509_V_ERR_CERT_CHAIN_TOO_LONG
+ CertRevoked VerifyResult = C.X509_V_ERR_CERT_REVOKED
+ InvalidCa VerifyResult = C.X509_V_ERR_INVALID_CA
+ PathLengthExceeded VerifyResult = C.X509_V_ERR_PATH_LENGTH_EXCEEDED
+ InvalidPurpose VerifyResult = C.X509_V_ERR_INVALID_PURPOSE
+ CertUntrusted VerifyResult = C.X509_V_ERR_CERT_UNTRUSTED
+ CertRejected VerifyResult = C.X509_V_ERR_CERT_REJECTED
+ SubjectIssuerMismatch VerifyResult = C.X509_V_ERR_SUBJECT_ISSUER_MISMATCH
+ AkidSkidMismatch VerifyResult = C.X509_V_ERR_AKID_SKID_MISMATCH
+ AkidIssuerSerialMismatch VerifyResult = C.X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH
+ KeyusageNoCertsign VerifyResult = C.X509_V_ERR_KEYUSAGE_NO_CERTSIGN
+ UnableToGetCrlIssuer VerifyResult = C.X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER
+ UnhandledCriticalExtension VerifyResult = C.X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION
+ KeyusageNoCrlSign VerifyResult = C.X509_V_ERR_KEYUSAGE_NO_CRL_SIGN
+ UnhandledCriticalCrlExtension VerifyResult = C.X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION
+ InvalidNonCa VerifyResult = C.X509_V_ERR_INVALID_NON_CA
+ ProxyPathLengthExceeded VerifyResult = C.X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED
+ KeyusageNoDigitalSignature VerifyResult = C.X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE
+ ProxyCertificatesNotAllowed VerifyResult = C.X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED
+ InvalidExtension VerifyResult = C.X509_V_ERR_INVALID_EXTENSION
+ InvalidPolicyExtension VerifyResult = C.X509_V_ERR_INVALID_POLICY_EXTENSION
+ NoExplicitPolicy VerifyResult = C.X509_V_ERR_NO_EXPLICIT_POLICY
+ UnnestedResource VerifyResult = C.X509_V_ERR_UNNESTED_RESOURCE
+ ApplicationVerification VerifyResult = C.X509_V_ERR_APPLICATION_VERIFICATION
+)
+
func newSSL(ctx *C.SSL_CTX) (*C.SSL, error) {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
@@ -141,6 +200,15 @@ func Server(conn net.Conn, ctx *Ctx) (*Conn, error) {
return c, nil
}
+func (c *Conn) CurrentCipher() (string, error) {
+ p := C.SSL_get_cipher_name_not_a_macro(c.ssl)
+ if p == nil {
+ return "", errors.New("Session not established")
+ }
+
+ return C.GoString(p), nil
+}
+
func (c *Conn) fillInputBuffer() error {
for {
n, err := c.into_ssl.ReadFromOnce(c.conn)
@@ -316,11 +384,13 @@ type ConnectionState struct {
CertificateError error
CertificateChain []*Certificate
CertificateChainError error
+ SessionReused bool
}
func (c *Conn) ConnectionState() (rv ConnectionState) {
rv.Certificate, rv.CertificateError = c.PeerCertificate()
rv.CertificateChain, rv.CertificateChainError = c.PeerCertificateChain()
+ rv.SessionReused = c.SessionReused()
return
}
@@ -500,3 +570,56 @@ func (c *Conn) UnderlyingConn() net.Conn {
return c.conn
}
+func (c *Conn) VerifyResult() VerifyResult {
+ return VerifyResult(C.SSL_get_verify_result(c.ssl))
+}
+
+func (c *Conn) SessionReused() bool {
+ return C.SSL_session_reused_not_a_macro(c.ssl) == 1
+}
+
+func (c *Conn) GetSession() ([]byte, error) {
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ // get1 increases the refcount of the session, so we have to free it.
+ session := (*C.SSL_SESSION)(C.SSL_get1_session(c.ssl))
+ if session == nil {
+ return nil, errors.New("failed to get session")
+ }
+ defer C.SSL_SESSION_free(session)
+
+ // get the size of the encoding
+ slen := C.i2d_SSL_SESSION(session, nil)
+
+ buf := (*C.uchar)(C.malloc(C.size_t(slen)))
+ defer C.free(unsafe.Pointer(buf))
+
+ // this modifies the value of buf (seriously), so we have to pass in a temp
+ // var so that we can actually read the bytes from buf.
+ tmp := buf
+ slen2 := C.i2d_SSL_SESSION(session, &tmp)
+ if slen != slen2 {
+ return nil, errors.New("session had different lengths")
+ }
+
+ return C.GoBytes(unsafe.Pointer(buf), slen), nil
+}
+
+func (c *Conn) setSession(session []byte) error {
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ptr := (*C.uchar)(&session[0])
+ s := C.d2i_SSL_SESSION(nil, &ptr, C.long(len(session)))
+ if s == nil {
+ return fmt.Errorf("unable to load session: %s", errorFromErrorQueue())
+ }
+ defer C.SSL_SESSION_free(s)
+
+ ret := C.SSL_set_session(c.ssl, s)
+ if ret != 1 {
+ return fmt.Errorf("unable to set session: %s", errorFromErrorQueue())
+ }
+ return nil
+}
diff --git a/vendor/src/github.com/spacemonkeygo/openssl/ctx.go b/vendor/src/github.com/spacemonkeygo/openssl/ctx.go
index 22d6dd16149..e8c1824f808 100644
--- a/vendor/src/github.com/spacemonkeygo/openssl/ctx.go
+++ b/vendor/src/github.com/spacemonkeygo/openssl/ctx.go
@@ -27,6 +27,14 @@ static long SSL_CTX_set_options_not_a_macro(SSL_CTX* ctx, long options) {
return SSL_CTX_set_options(ctx, options);
}
+static long SSL_CTX_clear_options_not_a_macro(SSL_CTX* ctx, long options) {
+ return SSL_CTX_clear_options(ctx, options);
+}
+
+static long SSL_CTX_get_options_not_a_macro(SSL_CTX* ctx) {
+ return SSL_CTX_get_options(ctx);
+}
+
static long SSL_CTX_set_mode_not_a_macro(SSL_CTX* ctx, long modes) {
return SSL_CTX_set_mode(ctx, modes);
}
@@ -39,6 +47,22 @@ static long SSL_CTX_set_session_cache_mode_not_a_macro(SSL_CTX* ctx, long modes)
return SSL_CTX_set_session_cache_mode(ctx, modes);
}
+static long SSL_CTX_sess_set_cache_size_not_a_macro(SSL_CTX* ctx, long t) {
+ return SSL_CTX_sess_set_cache_size(ctx, t);
+}
+
+static long SSL_CTX_sess_get_cache_size_not_a_macro(SSL_CTX* ctx) {
+ return SSL_CTX_sess_get_cache_size(ctx);
+}
+
+static long SSL_CTX_set_timeout_not_a_macro(SSL_CTX* ctx, long t) {
+ return SSL_CTX_set_timeout(ctx, t);
+}
+
+static long SSL_CTX_get_timeout_not_a_macro(SSL_CTX* ctx) {
+ return SSL_CTX_get_timeout(ctx);
+}
+
static int CRYPTO_add_not_a_macro(int *pointer,int amount,int type) {
return CRYPTO_add(pointer, amount, type);
}
@@ -56,7 +80,7 @@ static long SSL_CTX_add_extra_chain_cert_not_a_macro(SSL_CTX* ctx, X509 *cert) {
#endif
static const SSL_METHOD *OUR_TLSv1_1_method() {
-#ifdef TLS1_1_VERSION
+#if OPENSSL_VERSION_NUMBER > 0x1000100fL && defined(TLS1_1_VERSION) && !defined(OPENSSL_SYSNAME_MACOSX)
return TLSv1_1_method();
#else
return NULL;
@@ -64,13 +88,17 @@ static const SSL_METHOD *OUR_TLSv1_1_method() {
}
static const SSL_METHOD *OUR_TLSv1_2_method() {
-#ifdef TLS1_2_VERSION
+#if OPENSSL_VERSION_NUMBER > 0x1000100fL && defined(TLS1_2_VERSION) && !defined(OPENSSL_SYSNAME_MACOSX)
return TLSv1_2_method();
#else
return NULL;
#endif
}
+#if defined SSL_CTRL_SET_TLSEXT_HOSTNAME
+ extern int sni_cb(SSL *ssl_conn, int *ad, void *arg);
+#endif
+
extern int verify_cb(int ok, X509_STORE_CTX* store);
typedef STACK_OF(X509_NAME) *STACK_OF_X509_NAME_not_a_macro;
@@ -89,6 +117,7 @@ import (
"io/ioutil"
"os"
"runtime"
+ "time"
"unsafe"
"github.com/spacemonkeygo/spacelog"
@@ -102,7 +131,11 @@ var (
type Ctx struct {
ctx *C.SSL_CTX
+ cert *Certificate
+ chain []*Certificate
+ key PrivateKey
verify_cb VerifyCallback
+ sni_cb TLSExtServernameCallback
}
//export get_ssl_ctx_idx
@@ -128,10 +161,13 @@ func newCtx(method *C.SSL_METHOD) (*Ctx, error) {
type SSLVersion int
const (
- SSLv3 SSLVersion = 0x02
- TLSv1 SSLVersion = 0x03
- TLSv1_1 SSLVersion = 0x04
- TLSv1_2 SSLVersion = 0x05
+ SSLv3 SSLVersion = 0x02 // Vulnerable to "POODLE" attack.
+ TLSv1 SSLVersion = 0x03
+ TLSv1_1 SSLVersion = 0x04
+ TLSv1_2 SSLVersion = 0x05
+
+ // Make sure to disable SSLv2 and SSLv3 if you use this. SSLv3 is vulnerable
+ // to the "POODLE" attack, and SSLv2 is what, just don't even.
AnyVersion SSLVersion = 0x06
)
@@ -179,7 +215,12 @@ func NewCtxFromFiles(cert_file string, key_file string) (*Ctx, error) {
return nil, err
}
- cert, err := LoadCertificateFromPEM(cert_bytes)
+ certs := SplitPEM(cert_bytes)
+ if len(certs) == 0 {
+ return nil, fmt.Errorf("No PEM certificate found in '%s'", cert_file)
+ }
+ first, certs := certs[0], certs[1:]
+ cert, err := LoadCertificateFromPEM(first)
if err != nil {
return nil, err
}
@@ -189,6 +230,17 @@ func NewCtxFromFiles(cert_file string, key_file string) (*Ctx, error) {
return nil, err
}
+ for _, pem := range certs {
+ cert, err := LoadCertificateFromPEM(pem)
+ if err != nil {
+ return nil, err
+ }
+ err = ctx.AddChainCertificate(cert)
+ if err != nil {
+ return nil, err
+ }
+ }
+
key_bytes, err := ioutil.ReadFile(key_file)
if err != nil {
return nil, err
@@ -223,6 +275,7 @@ const (
func (c *Ctx) UseCertificate(cert *Certificate) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
+ c.cert = cert
if int(C.SSL_CTX_use_certificate(c.ctx, cert.x)) != 1 {
return errorFromErrorQueue()
}
@@ -345,9 +398,12 @@ func (c *Ctx) SetClientCAList(caList *StackOfX509Name) {
func (c *Ctx) AddChainCertificate(cert *Certificate) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
+ c.chain = append(c.chain, cert)
if int(C.SSL_CTX_add_extra_chain_cert_not_a_macro(c.ctx, cert.x)) != 1 {
return errorFromErrorQueue()
}
+ // OpenSSL takes ownership via SSL_CTX_add_extra_chain_cert
+ runtime.SetFinalizer(cert, nil)
return nil
}
@@ -356,6 +412,7 @@ func (c *Ctx) AddChainCertificate(cert *Certificate) error {
func (c *Ctx) UsePrivateKey(key PrivateKey) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
+ c.key = key
if int(C.SSL_CTX_use_PrivateKey(c.ctx, key.evpPKey())) != 1 {
return errorFromErrorQueue()
}
@@ -364,7 +421,38 @@ func (c *Ctx) UsePrivateKey(key PrivateKey) error {
type CertificateStore struct {
store *C.X509_STORE
- ctx *Ctx // for gc
+ // for GC
+ ctx *Ctx
+ certs []*Certificate
+}
+
+// Allocate a new, empty CertificateStore
+func NewCertificateStore() (*CertificateStore, error) {
+ s := C.X509_STORE_new()
+ if s == nil {
+ return nil, errors.New("failed to allocate X509_STORE")
+ }
+ store := &CertificateStore{store: s}
+ runtime.SetFinalizer(store, func(s *CertificateStore) {
+ C.X509_STORE_free(s.store)
+ })
+ return store, nil
+}
+
+// Parse a chained PEM file, loading all certificates into the Store.
+func (s *CertificateStore) LoadCertificatesFromPEM(data []byte) error {
+ pems := SplitPEM(data)
+ for _, pem := range pems {
+ cert, err := LoadCertificateFromPEM(pem)
+ if err != nil {
+ return err
+ }
+ err = s.AddCertificate(cert)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
}
// GetCertificateStore returns the context's certificate store that will be
@@ -382,6 +470,7 @@ func (c *Ctx) GetCertificateStore() *CertificateStore {
func (s *CertificateStore) AddCertificate(cert *Certificate) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
+ s.certs = append(s.certs, cert)
if int(C.X509_STORE_add_cert(s.store, cert.x)) != 1 {
return errorFromErrorQueue()
}
@@ -480,6 +569,10 @@ type CertificateStoreCtx struct {
ssl_ctx *Ctx
}
+func (self *CertificateStoreCtx) VerifyResult() VerifyResult {
+ return VerifyResult(C.X509_STORE_CTX_get_error(self.ctx))
+}
+
func (self *CertificateStoreCtx) Err() error {
code := C.X509_STORE_CTX_get_error(self.ctx)
if code == C.X509_V_OK {
@@ -553,6 +646,17 @@ func (c *Ctx) SetOptions(options Options) Options {
c.ctx, C.long(options)))
}
+func (c *Ctx) ClearOptions(options Options) Options {
+ return Options(C.SSL_CTX_clear_options_not_a_macro(
+ c.ctx, C.long(options)))
+}
+
+// GetOptions returns context options. See
+// https://www.openssl.org/docs/ssl/SSL_CTX_set_options.html
+func (c *Ctx) GetOptions() Options {
+ return Options(C.SSL_CTX_get_options_not_a_macro(c.ctx))
+}
+
type Modes int
const (
@@ -631,6 +735,10 @@ func (c *Ctx) SetVerifyCallback(verify_cb VerifyCallback) {
c.SetVerify(c.VerifyMode(), verify_cb)
}
+func (c *Ctx) GetVerifyCallback() VerifyCallback {
+ return c.verify_cb
+}
+
func (c *Ctx) VerifyMode() VerifyOptions {
return VerifyOptions(C.SSL_CTX_get_verify_mode(c.ctx))
}
@@ -642,6 +750,15 @@ func (c *Ctx) SetVerifyDepth(depth int) {
C.SSL_CTX_set_verify_depth(c.ctx, C.int(depth))
}
+// GetVerifyDepth controls how many certificates deep the certificate
+// verification logic is willing to follow a certificate chain. See
+// https://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html
+func (c *Ctx) GetVerifyDepth() int {
+ return int(C.SSL_CTX_get_verify_depth(c.ctx))
+}
+
+type TLSExtServernameCallback func(ssl *SSL) SSLTLSExtErr
+
func (c *Ctx) SetSessionId(session_id []byte) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
@@ -689,3 +806,28 @@ func (c *Ctx) SetSessionCacheMode(modes SessionCacheModes) SessionCacheModes {
return SessionCacheModes(
C.SSL_CTX_set_session_cache_mode_not_a_macro(c.ctx, C.long(modes)))
}
+
+// Set session cache timeout. Returns previously set value.
+// See https://www.openssl.org/docs/ssl/SSL_CTX_set_timeout.html
+func (c *Ctx) SetTimeout(t time.Duration) time.Duration {
+ prev := C.SSL_CTX_set_timeout_not_a_macro(c.ctx, C.long(t/time.Second))
+ return time.Duration(prev) * time.Second
+}
+
+// Get session cache timeout.
+// See https://www.openssl.org/docs/ssl/SSL_CTX_set_timeout.html
+func (c *Ctx) GetTimeout() time.Duration {
+ return time.Duration(C.SSL_CTX_get_timeout_not_a_macro(c.ctx)) * time.Second
+}
+
+// Set session cache size. Returns previously set value.
+// https://www.openssl.org/docs/ssl/SSL_CTX_sess_set_cache_size.html
+func (c *Ctx) SessSetCacheSize(t int) int {
+ return int(C.SSL_CTX_sess_set_cache_size_not_a_macro(c.ctx, C.long(t)))
+}
+
+// Get session cache size.
+// https://www.openssl.org/docs/ssl/SSL_CTX_sess_set_cache_size.html
+func (c *Ctx) SessGetCacheSize() int {
+ return int(C.SSL_CTX_sess_get_cache_size_not_a_macro(c.ctx))
+}
diff --git a/vendor/src/github.com/spacemonkeygo/openssl/ctx_test.go b/vendor/src/github.com/spacemonkeygo/openssl/ctx_test.go
new file mode 100644
index 00000000000..9644e518bf3
--- /dev/null
+++ b/vendor/src/github.com/spacemonkeygo/openssl/ctx_test.go
@@ -0,0 +1,48 @@
+// Copyright (C) 2014 Ryan Hileman
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package openssl
+
+import (
+ "testing"
+ "time"
+)
+
+func TestCtxTimeoutOption(t *testing.T) {
+ ctx, _ := NewCtx()
+ oldTimeout1 := ctx.GetTimeout()
+ newTimeout1 := oldTimeout1 + (time.Duration(99) * time.Second)
+ oldTimeout2 := ctx.SetTimeout(newTimeout1)
+ newTimeout2 := ctx.GetTimeout()
+ if oldTimeout1 != oldTimeout2 {
+ t.Error("SetTimeout() returns something undocumented")
+ }
+ if newTimeout1 != newTimeout2 {
+ t.Error("SetTimeout() does not save anything to ctx")
+ }
+}
+
+func TestCtxSessCacheSizeOption(t *testing.T) {
+ ctx, _ := NewCtx()
+ oldSize1 := ctx.SessGetCacheSize()
+ newSize1 := oldSize1 + 42
+ oldSize2 := ctx.SessSetCacheSize(newSize1)
+ newSize2 := ctx.SessGetCacheSize()
+ if oldSize1 != oldSize2 {
+ t.Error("SessSetCacheSize() returns something undocumented")
+ }
+ if newSize1 != newSize2 {
+ t.Error("SessSetCacheSize() does not save anything to ctx")
+ }
+}
diff --git a/vendor/src/github.com/spacemonkeygo/openssl/dhparam.go b/vendor/src/github.com/spacemonkeygo/openssl/dhparam.go
new file mode 100644
index 00000000000..a698645c1ec
--- /dev/null
+++ b/vendor/src/github.com/spacemonkeygo/openssl/dhparam.go
@@ -0,0 +1,65 @@
+// +build cgo
+
+package openssl
+
+/*
+#include <openssl/crypto.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/conf.h>
+#include <openssl/dh.h>
+
+static long SSL_CTX_set_tmp_dh_not_a_macro(SSL_CTX* ctx, DH *dh) {
+ return SSL_CTX_set_tmp_dh(ctx, dh);
+}
+static long PEM_read_DHparams_not_a_macro(SSL_CTX* ctx, DH *dh) {
+ return SSL_CTX_set_tmp_dh(ctx, dh);
+}
+*/
+import "C"
+
+import (
+ "errors"
+ "runtime"
+ "unsafe"
+)
+
+type DH struct {
+ dh *C.struct_dh_st
+}
+
+// LoadDHParametersFromPEM loads the Diffie-Hellman parameters from
+// a PEM-encoded block.
+func LoadDHParametersFromPEM(pem_block []byte) (*DH, error) {
+ if len(pem_block) == 0 {
+ return nil, errors.New("empty pem block")
+ }
+ bio := C.BIO_new_mem_buf(unsafe.Pointer(&pem_block[0]),
+ C.int(len(pem_block)))
+ if bio == nil {
+ return nil, errors.New("failed creating bio")
+ }
+ defer C.BIO_free(bio)
+
+ params := C.PEM_read_bio_DHparams(bio, nil, nil, nil)
+ if params == nil {
+ return nil, errors.New("failed reading dh parameters")
+ }
+ dhparams := &DH{dh: params}
+ runtime.SetFinalizer(dhparams, func(dhparams *DH) {
+ C.DH_free(dhparams.dh)
+ })
+ return dhparams, nil
+}
+
+// SetDHParameters sets the DH group (DH parameters) used to
+// negotiate an emphemeral DH key during handshaking.
+func (c *Ctx) SetDHParameters(dh *DH) error {
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ if int(C.SSL_CTX_set_tmp_dh_not_a_macro(c.ctx, dh.dh)) != 1 {
+ return errorFromErrorQueue()
+ }
+ return nil
+}
diff --git a/vendor/src/github.com/spacemonkeygo/openssl/digest.go b/vendor/src/github.com/spacemonkeygo/openssl/digest.go
new file mode 100644
index 00000000000..44d4d001b13
--- /dev/null
+++ b/vendor/src/github.com/spacemonkeygo/openssl/digest.go
@@ -0,0 +1,53 @@
+// Copyright (C) 2015 Space Monkey, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build cgo
+
+package openssl
+
+// #include <openssl/evp.h>
+import "C"
+
+import (
+ "fmt"
+ "unsafe"
+)
+
+// Digest represents and openssl message digest.
+type Digest struct {
+ ptr *C.EVP_MD
+}
+
+// GetDigestByName returns the Digest with the name or nil and an error if the
+// digest was not found.
+func GetDigestByName(name string) (*Digest, error) {
+ cname := C.CString(name)
+ defer C.free(unsafe.Pointer(cname))
+ p := C.EVP_get_digestbyname(cname)
+ if p == nil {
+ return nil, fmt.Errorf("Digest %v not found", name)
+ }
+ // we can consider digests to use static mem; don't need to free
+ return &Digest{ptr: p}, nil
+}
+
+// GetDigestByName returns the Digest with the NID or nil and an error if the
+// digest was not found.
+func GetDigestByNid(nid NID) (*Digest, error) {
+ sn, err := Nid2ShortName(nid)
+ if err != nil {
+ return nil, err
+ }
+ return GetDigestByName(sn)
+}
diff --git a/vendor/src/github.com/spacemonkeygo/openssl/key.go b/vendor/src/github.com/spacemonkeygo/openssl/key.go
new file mode 100644
index 00000000000..c69a101631f
--- /dev/null
+++ b/vendor/src/github.com/spacemonkeygo/openssl/key.go
@@ -0,0 +1,374 @@
+// Copyright (C) 2014 Space Monkey, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build cgo
+
+package openssl
+
+// #include <openssl/evp.h>
+// #include <openssl/ssl.h>
+// #include <openssl/conf.h>
+//
+// int EVP_SignInit_not_a_macro(EVP_MD_CTX *ctx, const EVP_MD *type) {
+// return EVP_SignInit(ctx, type);
+// }
+//
+// int EVP_SignUpdate_not_a_macro(EVP_MD_CTX *ctx, const void *d,
+// unsigned int cnt) {
+// return EVP_SignUpdate(ctx, d, cnt);
+// }
+//
+// int EVP_VerifyInit_not_a_macro(EVP_MD_CTX *ctx, const EVP_MD *type) {
+// return EVP_VerifyInit(ctx, type);
+// }
+//
+// int EVP_VerifyUpdate_not_a_macro(EVP_MD_CTX *ctx, const void *d,
+// unsigned int cnt) {
+// return EVP_VerifyUpdate(ctx, d, cnt);
+// }
+//
+// int EVP_PKEY_assign_charp(EVP_PKEY *pkey, int type, char *key) {
+// return EVP_PKEY_assign(pkey, type, key);
+// }
+import "C"
+
+import (
+ "errors"
+ "io/ioutil"
+ "runtime"
+ "unsafe"
+)
+
+type Method *C.EVP_MD
+
+var (
+ SHA256_Method Method = C.EVP_sha256()
+)
+
+type PublicKey interface {
+ // Verifies the data signature using PKCS1.15
+ VerifyPKCS1v15(method Method, data, sig []byte) error
+
+ // MarshalPKIXPublicKeyPEM converts the public key to PEM-encoded PKIX
+ // format
+ MarshalPKIXPublicKeyPEM() (pem_block []byte, err error)
+
+ // MarshalPKIXPublicKeyDER converts the public key to DER-encoded PKIX
+ // format
+ MarshalPKIXPublicKeyDER() (der_block []byte, err error)
+
+ evpPKey() *C.EVP_PKEY
+}
+
+type PrivateKey interface {
+ PublicKey
+
+ // Signs the data using PKCS1.15
+ SignPKCS1v15(Method, []byte) ([]byte, error)
+
+ // MarshalPKCS1PrivateKeyPEM converts the private key to PEM-encoded PKCS1
+ // format
+ MarshalPKCS1PrivateKeyPEM() (pem_block []byte, err error)
+
+ // MarshalPKCS1PrivateKeyDER converts the private key to DER-encoded PKCS1
+ // format
+ MarshalPKCS1PrivateKeyDER() (der_block []byte, err error)
+}
+
+type pKey struct {
+ key *C.EVP_PKEY
+}
+
+func (key *pKey) evpPKey() *C.EVP_PKEY { return key.key }
+
+func (key *pKey) SignPKCS1v15(method Method, data []byte) ([]byte, error) {
+ var ctx C.EVP_MD_CTX
+ C.EVP_MD_CTX_init(&ctx)
+ defer C.EVP_MD_CTX_cleanup(&ctx)
+
+ if 1 != C.EVP_SignInit_not_a_macro(&ctx, method) {
+ return nil, errors.New("signpkcs1v15: failed to init signature")
+ }
+ if len(data) > 0 {
+ if 1 != C.EVP_SignUpdate_not_a_macro(
+ &ctx, unsafe.Pointer(&data[0]), C.uint(len(data))) {
+ return nil, errors.New("signpkcs1v15: failed to update signature")
+ }
+ }
+ sig := make([]byte, C.EVP_PKEY_size(key.key))
+ var sigblen C.uint
+ if 1 != C.EVP_SignFinal(&ctx,
+ ((*C.uchar)(unsafe.Pointer(&sig[0]))), &sigblen, key.key) {
+ return nil, errors.New("signpkcs1v15: failed to finalize signature")
+ }
+ return sig[:sigblen], nil
+}
+
+func (key *pKey) VerifyPKCS1v15(method Method, data, sig []byte) error {
+ var ctx C.EVP_MD_CTX
+ C.EVP_MD_CTX_init(&ctx)
+ defer C.EVP_MD_CTX_cleanup(&ctx)
+
+ if 1 != C.EVP_VerifyInit_not_a_macro(&ctx, method) {
+ return errors.New("verifypkcs1v15: failed to init verify")
+ }
+ if len(data) > 0 {
+ if 1 != C.EVP_VerifyUpdate_not_a_macro(
+ &ctx, unsafe.Pointer(&data[0]), C.uint(len(data))) {
+ return errors.New("verifypkcs1v15: failed to update verify")
+ }
+ }
+ if 1 != C.EVP_VerifyFinal(&ctx,
+ ((*C.uchar)(unsafe.Pointer(&sig[0]))), C.uint(len(sig)), key.key) {
+ return errors.New("verifypkcs1v15: failed to finalize verify")
+ }
+ return nil
+}
+
+func (key *pKey) MarshalPKCS1PrivateKeyPEM() (pem_block []byte,
+ err error) {
+ bio := C.BIO_new(C.BIO_s_mem())
+ if bio == nil {
+ return nil, errors.New("failed to allocate memory BIO")
+ }
+ defer C.BIO_free(bio)
+ rsa := (*C.RSA)(C.EVP_PKEY_get1_RSA(key.key))
+ if rsa == nil {
+ return nil, errors.New("failed getting rsa key")
+ }
+ defer C.RSA_free(rsa)
+ if int(C.PEM_write_bio_RSAPrivateKey(bio, rsa, nil, nil, C.int(0), nil,
+ nil)) != 1 {
+ return nil, errors.New("failed dumping private key")
+ }
+ return ioutil.ReadAll(asAnyBio(bio))
+}
+
+func (key *pKey) MarshalPKCS1PrivateKeyDER() (der_block []byte,
+ err error) {
+ bio := C.BIO_new(C.BIO_s_mem())
+ if bio == nil {
+ return nil, errors.New("failed to allocate memory BIO")
+ }
+ defer C.BIO_free(bio)
+ rsa := (*C.RSA)(C.EVP_PKEY_get1_RSA(key.key))
+ if rsa == nil {
+ return nil, errors.New("failed getting rsa key")
+ }
+ defer C.RSA_free(rsa)
+ if int(C.i2d_RSAPrivateKey_bio(bio, rsa)) != 1 {
+ return nil, errors.New("failed dumping private key der")
+ }
+ return ioutil.ReadAll(asAnyBio(bio))
+}
+
+func (key *pKey) MarshalPKIXPublicKeyPEM() (pem_block []byte,
+ err error) {
+ bio := C.BIO_new(C.BIO_s_mem())
+ if bio == nil {
+ return nil, errors.New("failed to allocate memory BIO")
+ }
+ defer C.BIO_free(bio)
+ rsa := (*C.RSA)(C.EVP_PKEY_get1_RSA(key.key))
+ if rsa == nil {
+ return nil, errors.New("failed getting rsa key")
+ }
+ defer C.RSA_free(rsa)
+ if int(C.PEM_write_bio_RSA_PUBKEY(bio, rsa)) != 1 {
+ return nil, errors.New("failed dumping public key pem")
+ }
+ return ioutil.ReadAll(asAnyBio(bio))
+}
+
+func (key *pKey) MarshalPKIXPublicKeyDER() (der_block []byte,
+ err error) {
+ bio := C.BIO_new(C.BIO_s_mem())
+ if bio == nil {
+ return nil, errors.New("failed to allocate memory BIO")
+ }
+ defer C.BIO_free(bio)
+ rsa := (*C.RSA)(C.EVP_PKEY_get1_RSA(key.key))
+ if rsa == nil {
+ return nil, errors.New("failed getting rsa key")
+ }
+ defer C.RSA_free(rsa)
+ if int(C.i2d_RSA_PUBKEY_bio(bio, rsa)) != 1 {
+ return nil, errors.New("failed dumping public key der")
+ }
+ return ioutil.ReadAll(asAnyBio(bio))
+}
+
+// LoadPrivateKeyFromPEM loads a private key from a PEM-encoded block.
+func LoadPrivateKeyFromPEM(pem_block []byte) (PrivateKey, error) {
+ if len(pem_block) == 0 {
+ return nil, errors.New("empty pem block")
+ }
+ bio := C.BIO_new_mem_buf(unsafe.Pointer(&pem_block[0]),
+ C.int(len(pem_block)))
+ if bio == nil {
+ return nil, errors.New("failed creating bio")
+ }
+ defer C.BIO_free(bio)
+
+ rsakey := C.PEM_read_bio_RSAPrivateKey(bio, nil, nil, nil)
+ if rsakey == nil {
+ return nil, errors.New("failed reading rsa key")
+ }
+ defer C.RSA_free(rsakey)
+
+ // convert to PKEY
+ key := C.EVP_PKEY_new()
+ if key == nil {
+ return nil, errors.New("failed converting to evp_pkey")
+ }
+ if C.EVP_PKEY_set1_RSA(key, (*C.struct_rsa_st)(rsakey)) != 1 {
+ C.EVP_PKEY_free(key)
+ return nil, errors.New("failed converting to evp_pkey")
+ }
+
+ p := &pKey{key: key}
+ runtime.SetFinalizer(p, func(p *pKey) {
+ C.EVP_PKEY_free(p.key)
+ })
+ return p, nil
+}
+
+// LoadPrivateKeyFromPEM loads a private key from a PEM-encoded block.
+func LoadPrivateKeyFromPEMWidthPassword(pem_block []byte, password string) (
+ PrivateKey, error) {
+ if len(pem_block) == 0 {
+ return nil, errors.New("empty pem block")
+ }
+ bio := C.BIO_new_mem_buf(unsafe.Pointer(&pem_block[0]),
+ C.int(len(pem_block)))
+ if bio == nil {
+ return nil, errors.New("failed creating bio")
+ }
+ defer C.BIO_free(bio)
+ cs := C.CString(password)
+ defer C.free(unsafe.Pointer(cs))
+ rsakey := C.PEM_read_bio_RSAPrivateKey(bio, nil, nil, unsafe.Pointer(cs))
+ if rsakey == nil {
+ return nil, errors.New("failed reading rsa key")
+ }
+ defer C.RSA_free(rsakey)
+
+ // convert to PKEY
+ key := C.EVP_PKEY_new()
+ if key == nil {
+ return nil, errors.New("failed converting to evp_pkey")
+ }
+ if C.EVP_PKEY_set1_RSA(key, (*C.struct_rsa_st)(rsakey)) != 1 {
+ C.EVP_PKEY_free(key)
+ return nil, errors.New("failed converting to evp_pkey")
+ }
+
+ p := &pKey{key: key}
+ runtime.SetFinalizer(p, func(p *pKey) {
+ C.EVP_PKEY_free(p.key)
+ })
+ return p, nil
+}
+
+// LoadPublicKeyFromPEM loads a public key from a PEM-encoded block.
+func LoadPublicKeyFromPEM(pem_block []byte) (PublicKey, error) {
+ if len(pem_block) == 0 {
+ return nil, errors.New("empty pem block")
+ }
+ bio := C.BIO_new_mem_buf(unsafe.Pointer(&pem_block[0]),
+ C.int(len(pem_block)))
+ if bio == nil {
+ return nil, errors.New("failed creating bio")
+ }
+ defer C.BIO_free(bio)
+
+ rsakey := C.PEM_read_bio_RSA_PUBKEY(bio, nil, nil, nil)
+ if rsakey == nil {
+ return nil, errors.New("failed reading rsa key")
+ }
+ defer C.RSA_free(rsakey)
+
+ // convert to PKEY
+ key := C.EVP_PKEY_new()
+ if key == nil {
+ return nil, errors.New("failed converting to evp_pkey")
+ }
+ if C.EVP_PKEY_set1_RSA(key, (*C.struct_rsa_st)(rsakey)) != 1 {
+ C.EVP_PKEY_free(key)
+ return nil, errors.New("failed converting to evp_pkey")
+ }
+
+ p := &pKey{key: key}
+ runtime.SetFinalizer(p, func(p *pKey) {
+ C.EVP_PKEY_free(p.key)
+ })
+ return p, nil
+}
+
+// LoadPublicKeyFromDER loads a public key from a DER-encoded block.
+func LoadPublicKeyFromDER(der_block []byte) (PublicKey, error) {
+ if len(der_block) == 0 {
+ return nil, errors.New("empty der block")
+ }
+ bio := C.BIO_new_mem_buf(unsafe.Pointer(&der_block[0]),
+ C.int(len(der_block)))
+ if bio == nil {
+ return nil, errors.New("failed creating bio")
+ }
+ defer C.BIO_free(bio)
+
+ rsakey := C.d2i_RSA_PUBKEY_bio(bio, nil)
+ if rsakey == nil {
+ return nil, errors.New("failed reading rsa key")
+ }
+ defer C.RSA_free(rsakey)
+
+ // convert to PKEY
+ key := C.EVP_PKEY_new()
+ if key == nil {
+ return nil, errors.New("failed converting to evp_pkey")
+ }
+ if C.EVP_PKEY_set1_RSA(key, (*C.struct_rsa_st)(rsakey)) != 1 {
+ C.EVP_PKEY_free(key)
+ return nil, errors.New("failed converting to evp_pkey")
+ }
+
+ p := &pKey{key: key}
+ runtime.SetFinalizer(p, func(p *pKey) {
+ C.EVP_PKEY_free(p.key)
+ })
+ return p, nil
+}
+
+// GenerateRSAKey generates a new RSA private key with an exponent of 3.
+func GenerateRSAKey(bits int) (PrivateKey, error) {
+ exponent := 3
+ rsa := C.RSA_generate_key(C.int(bits), C.ulong(exponent), nil, nil)
+ if rsa == nil {
+ return nil, errors.New("failed to generate RSA key")
+ }
+ key := C.EVP_PKEY_new()
+ if key == nil {
+ return nil, errors.New("failed to allocate EVP_PKEY")
+ }
+ if C.EVP_PKEY_assign_charp(key, C.EVP_PKEY_RSA, (*C.char)(unsafe.Pointer(rsa))) != 1 {
+ C.EVP_PKEY_free(key)
+ return nil, errors.New("failed to assign RSA key")
+ }
+ p := &pKey{key: key}
+ runtime.SetFinalizer(p, func(p *pKey) {
+ C.EVP_PKEY_free(p.key)
+ })
+ return p, nil
+}
diff --git a/vendor/src/github.com/spacemonkeygo/openssl/pem_test.go b/vendor/src/github.com/spacemonkeygo/openssl/key_test.go
index a79dc305fef..54752d381bf 100644
--- a/vendor/src/github.com/spacemonkeygo/openssl/pem_test.go
+++ b/vendor/src/github.com/spacemonkeygo/openssl/key_test.go
@@ -132,3 +132,18 @@ func TestMarshal(t *testing.T) {
t.Fatal("invalid public key der bytes")
}
}
+
+func TestGenerate(t *testing.T) {
+ key, err := GenerateRSAKey(2048)
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = key.MarshalPKIXPublicKeyPEM()
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = key.MarshalPKCS1PrivateKeyPEM()
+ if err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/vendor/src/github.com/spacemonkeygo/openssl/net.go b/vendor/src/github.com/spacemonkeygo/openssl/net.go
index 275f5c27b97..3cdd040d4d4 100644
--- a/vendor/src/github.com/spacemonkeygo/openssl/net.go
+++ b/vendor/src/github.com/spacemonkeygo/openssl/net.go
@@ -77,6 +77,25 @@ const (
// This library is not nice enough to use the system certificate store by
// default for you yet.
func Dial(network, addr string, ctx *Ctx, flags DialFlags) (*Conn, error) {
+ return DialSession(network, addr, ctx, flags, nil)
+}
+
+// DialSession will connect to network/address and then wrap the corresponding
+// underlying connection with an OpenSSL client connection using context ctx.
+// If flags includes InsecureSkipHostVerification, the server certificate's
+// hostname will not be checked to match the hostname in addr. Otherwise, flags
+// should be 0.
+//
+// Dial probably won't work for you unless you set a verify location or add
+// some certs to the certificate store of the client context you're using.
+// This library is not nice enough to use the system certificate store by
+// default for you yet.
+//
+// If session is not nil it will be used to resume the tls state. The session
+// can be retrieved from the GetSession method on the Conn.
+func DialSession(network, addr string, ctx *Ctx, flags DialFlags,
+ session []byte) (*Conn, error) {
+
host, _, err := net.SplitHostPort(addr)
if err != nil {
return nil, err
diff --git a/vendor/src/github.com/spacemonkeygo/openssl/nid.go b/vendor/src/github.com/spacemonkeygo/openssl/nid.go
new file mode 100644
index 00000000000..c80f237b605
--- /dev/null
+++ b/vendor/src/github.com/spacemonkeygo/openssl/nid.go
@@ -0,0 +1,199 @@
+// Copyright (C) 2014 Ryan Hileman
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package openssl
+
+type NID int
+
+const (
+ NID_rsadsi NID = 1
+ NID_pkcs NID = 2
+ NID_md2 NID = 3
+ NID_md5 NID = 4
+ NID_rc4 NID = 5
+ NID_rsaEncryption NID = 6
+ NID_md2WithRSAEncryption NID = 7
+ NID_md5WithRSAEncryption NID = 8
+ NID_pbeWithMD2AndDES_CBC NID = 9
+ NID_pbeWithMD5AndDES_CBC NID = 10
+ NID_X500 NID = 11
+ NID_X509 NID = 12
+ NID_commonName NID = 13
+ NID_countryName NID = 14
+ NID_localityName NID = 15
+ NID_stateOrProvinceName NID = 16
+ NID_organizationName NID = 17
+ NID_organizationalUnitName NID = 18
+ NID_rsa NID = 19
+ NID_pkcs7 NID = 20
+ NID_pkcs7_data NID = 21
+ NID_pkcs7_signed NID = 22
+ NID_pkcs7_enveloped NID = 23
+ NID_pkcs7_signedAndEnveloped NID = 24
+ NID_pkcs7_digest NID = 25
+ NID_pkcs7_encrypted NID = 26
+ NID_pkcs3 NID = 27
+ NID_dhKeyAgreement NID = 28
+ NID_des_ecb NID = 29
+ NID_des_cfb64 NID = 30
+ NID_des_cbc NID = 31
+ NID_des_ede NID = 32
+ NID_des_ede3 NID = 33
+ NID_idea_cbc NID = 34
+ NID_idea_cfb64 NID = 35
+ NID_idea_ecb NID = 36
+ NID_rc2_cbc NID = 37
+ NID_rc2_ecb NID = 38
+ NID_rc2_cfb64 NID = 39
+ NID_rc2_ofb64 NID = 40
+ NID_sha NID = 41
+ NID_shaWithRSAEncryption NID = 42
+ NID_des_ede_cbc NID = 43
+ NID_des_ede3_cbc NID = 44
+ NID_des_ofb64 NID = 45
+ NID_idea_ofb64 NID = 46
+ NID_pkcs9 NID = 47
+ NID_pkcs9_emailAddress NID = 48
+ NID_pkcs9_unstructuredName NID = 49
+ NID_pkcs9_contentType NID = 50
+ NID_pkcs9_messageDigest NID = 51
+ NID_pkcs9_signingTime NID = 52
+ NID_pkcs9_countersignature NID = 53
+ NID_pkcs9_challengePassword NID = 54
+ NID_pkcs9_unstructuredAddress NID = 55
+ NID_pkcs9_extCertAttributes NID = 56
+ NID_netscape NID = 57
+ NID_netscape_cert_extension NID = 58
+ NID_netscape_data_type NID = 59
+ NID_des_ede_cfb64 NID = 60
+ NID_des_ede3_cfb64 NID = 61
+ NID_des_ede_ofb64 NID = 62
+ NID_des_ede3_ofb64 NID = 63
+ NID_sha1 NID = 64
+ NID_sha1WithRSAEncryption NID = 65
+ NID_dsaWithSHA NID = 66
+ NID_dsa_2 NID = 67
+ NID_pbeWithSHA1AndRC2_CBC NID = 68
+ NID_id_pbkdf2 NID = 69
+ NID_dsaWithSHA1_2 NID = 70
+ NID_netscape_cert_type NID = 71
+ NID_netscape_base_url NID = 72
+ NID_netscape_revocation_url NID = 73
+ NID_netscape_ca_revocation_url NID = 74
+ NID_netscape_renewal_url NID = 75
+ NID_netscape_ca_policy_url NID = 76
+ NID_netscape_ssl_server_name NID = 77
+ NID_netscape_comment NID = 78
+ NID_netscape_cert_sequence NID = 79
+ NID_desx_cbc NID = 80
+ NID_id_ce NID = 81
+ NID_subject_key_identifier NID = 82
+ NID_key_usage NID = 83
+ NID_private_key_usage_period NID = 84
+ NID_subject_alt_name NID = 85
+ NID_issuer_alt_name NID = 86
+ NID_basic_constraints NID = 87
+ NID_crl_number NID = 88
+ NID_certificate_policies NID = 89
+ NID_authority_key_identifier NID = 90
+ NID_bf_cbc NID = 91
+ NID_bf_ecb NID = 92
+ NID_bf_cfb64 NID = 93
+ NID_bf_ofb64 NID = 94
+ NID_mdc2 NID = 95
+ NID_mdc2WithRSA NID = 96
+ NID_rc4_40 NID = 97
+ NID_rc2_40_cbc NID = 98
+ NID_givenName NID = 99
+ NID_surname NID = 100
+ NID_initials NID = 101
+ NID_uniqueIdentifier NID = 102
+ NID_crl_distribution_points NID = 103
+ NID_md5WithRSA NID = 104
+ NID_serialNumber NID = 105
+ NID_title NID = 106
+ NID_description NID = 107
+ NID_cast5_cbc NID = 108
+ NID_cast5_ecb NID = 109
+ NID_cast5_cfb64 NID = 110
+ NID_cast5_ofb64 NID = 111
+ NID_pbeWithMD5AndCast5_CBC NID = 112
+ NID_dsaWithSHA1 NID = 113
+ NID_md5_sha1 NID = 114
+ NID_sha1WithRSA NID = 115
+ NID_dsa NID = 116
+ NID_ripemd160 NID = 117
+ NID_ripemd160WithRSA NID = 119
+ NID_rc5_cbc NID = 120
+ NID_rc5_ecb NID = 121
+ NID_rc5_cfb64 NID = 122
+ NID_rc5_ofb64 NID = 123
+ NID_rle_compression NID = 124
+ NID_zlib_compression NID = 125
+ NID_ext_key_usage NID = 126
+ NID_id_pkix NID = 127
+ NID_id_kp NID = 128
+ NID_server_auth NID = 129
+ NID_client_auth NID = 130
+ NID_code_sign NID = 131
+ NID_email_protect NID = 132
+ NID_time_stamp NID = 133
+ NID_ms_code_ind NID = 134
+ NID_ms_code_com NID = 135
+ NID_ms_ctl_sign NID = 136
+ NID_ms_sgc NID = 137
+ NID_ms_efs NID = 138
+ NID_ns_sgc NID = 139
+ NID_delta_crl NID = 140
+ NID_crl_reason NID = 141
+ NID_invalidity_date NID = 142
+ NID_sxnet NID = 143
+ NID_pbe_WithSHA1And128BitRC4 NID = 144
+ NID_pbe_WithSHA1And40BitRC4 NID = 145
+ NID_pbe_WithSHA1And3_Key_TripleDES_CBC NID = 146
+ NID_pbe_WithSHA1And2_Key_TripleDES_CBC NID = 147
+ NID_pbe_WithSHA1And128BitRC2_CBC NID = 148
+ NID_pbe_WithSHA1And40BitRC2_CBC NID = 149
+ NID_keyBag NID = 150
+ NID_pkcs8ShroudedKeyBag NID = 151
+ NID_certBag NID = 152
+ NID_crlBag NID = 153
+ NID_secretBag NID = 154
+ NID_safeContentsBag NID = 155
+ NID_friendlyName NID = 156
+ NID_localKeyID NID = 157
+ NID_x509Certificate NID = 158
+ NID_sdsiCertificate NID = 159
+ NID_x509Crl NID = 160
+ NID_pbes2 NID = 161
+ NID_pbmac1 NID = 162
+ NID_hmacWithSHA1 NID = 163
+ NID_id_qt_cps NID = 164
+ NID_id_qt_unotice NID = 165
+ NID_rc2_64_cbc NID = 166
+ NID_SMIMECapabilities NID = 167
+ NID_pbeWithMD2AndRC2_CBC NID = 168
+ NID_pbeWithMD5AndRC2_CBC NID = 169
+ NID_pbeWithSHA1AndDES_CBC NID = 170
+ NID_ms_ext_req NID = 171
+ NID_ext_req NID = 172
+ NID_name NID = 173
+ NID_dnQualifier NID = 174
+ NID_id_pe NID = 175
+ NID_id_ad NID = 176
+ NID_info_access NID = 177
+ NID_ad_OCSP NID = 178
+ NID_ad_ca_issuers NID = 179
+ NID_OCSP_sign NID = 180
+)
diff --git a/vendor/src/github.com/spacemonkeygo/openssl/pem.go b/vendor/src/github.com/spacemonkeygo/openssl/pem.go
index e435480e26c..6dad5972dbd 100644
--- a/vendor/src/github.com/spacemonkeygo/openssl/pem.go
+++ b/vendor/src/github.com/spacemonkeygo/openssl/pem.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2014 Space Monkey, Inc.
+// Copyright (C) 2014 Ryan Hileman
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,379 +12,21 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// +build cgo
-
package openssl
-// #include <openssl/evp.h>
-// #include <openssl/ssl.h>
-// #include <openssl/conf.h>
-//
-// void OPENSSL_free_not_a_macro(void *ref) { OPENSSL_free(ref); }
-//
-// int EVP_SignInit_not_a_macro(EVP_MD_CTX *ctx, const EVP_MD *type) {
-// return EVP_SignInit(ctx, type);
-// }
-//
-// int EVP_SignUpdate_not_a_macro(EVP_MD_CTX *ctx, const void *d,
-// unsigned int cnt) {
-// return EVP_SignUpdate(ctx, d, cnt);
-// }
-//
-// int EVP_VerifyInit_not_a_macro(EVP_MD_CTX *ctx, const EVP_MD *type) {
-// return EVP_VerifyInit(ctx, type);
-// }
-//
-// int EVP_VerifyUpdate_not_a_macro(EVP_MD_CTX *ctx, const void *d,
-// unsigned int cnt) {
-// return EVP_VerifyUpdate(ctx, d, cnt);
-// }
-import "C"
-
import (
- "errors"
- "io/ioutil"
- "runtime"
- "unsafe"
+ "regexp"
)
-type Method *C.EVP_MD
-
-var (
- SHA256_Method Method = C.EVP_sha256()
-)
-
-type PublicKey interface {
- // Verifies the data signature using PKCS1.15
- VerifyPKCS1v15(method Method, data, sig []byte) error
-
- // MarshalPKIXPublicKeyPEM converts the public key to PEM-encoded PKIX
- // format
- MarshalPKIXPublicKeyPEM() (pem_block []byte, err error)
-
- // MarshalPKIXPublicKeyDER converts the public key to DER-encoded PKIX
- // format
- MarshalPKIXPublicKeyDER() (der_block []byte, err error)
-
- evpPKey() *C.EVP_PKEY
-}
-
-type PrivateKey interface {
- PublicKey
-
- // Signs the data using PKCS1.15
- SignPKCS1v15(Method, []byte) ([]byte, error)
-
- // MarshalPKCS1PrivateKeyPEM converts the private key to PEM-encoded PKCS1
- // format
- MarshalPKCS1PrivateKeyPEM() (pem_block []byte, err error)
-
- // MarshalPKCS1PrivateKeyDER converts the private key to DER-encoded PKCS1
- // format
- MarshalPKCS1PrivateKeyDER() (der_block []byte, err error)
-}
-
-type pKey struct {
- key *C.EVP_PKEY
-}
-
-func (key *pKey) evpPKey() *C.EVP_PKEY { return key.key }
-
-func (key *pKey) SignPKCS1v15(method Method, data []byte) ([]byte, error) {
- var ctx C.EVP_MD_CTX
- C.EVP_MD_CTX_init(&ctx)
- defer C.EVP_MD_CTX_cleanup(&ctx)
-
- if 1 != C.EVP_SignInit_not_a_macro(&ctx, method) {
- return nil, errors.New("signpkcs1v15: failed to init signature")
- }
- if len(data) > 0 {
- if 1 != C.EVP_SignUpdate_not_a_macro(
- &ctx, unsafe.Pointer(&data[0]), C.uint(len(data))) {
- return nil, errors.New("signpkcs1v15: failed to update signature")
- }
- }
- sig := make([]byte, C.EVP_PKEY_size(key.key))
- var sigblen C.uint
- if 1 != C.EVP_SignFinal(&ctx,
- ((*C.uchar)(unsafe.Pointer(&sig[0]))), &sigblen, key.key) {
- return nil, errors.New("signpkcs1v15: failed to finalize signature")
- }
- return sig[:sigblen], nil
-}
-
-func (key *pKey) VerifyPKCS1v15(method Method, data, sig []byte) error {
- var ctx C.EVP_MD_CTX
- C.EVP_MD_CTX_init(&ctx)
- defer C.EVP_MD_CTX_cleanup(&ctx)
-
- if 1 != C.EVP_VerifyInit_not_a_macro(&ctx, method) {
- return errors.New("verifypkcs1v15: failed to init verify")
- }
- if len(data) > 0 {
- if 1 != C.EVP_VerifyUpdate_not_a_macro(
- &ctx, unsafe.Pointer(&data[0]), C.uint(len(data))) {
- return errors.New("verifypkcs1v15: failed to update verify")
- }
- }
- if 1 != C.EVP_VerifyFinal(&ctx,
- ((*C.uchar)(unsafe.Pointer(&sig[0]))), C.uint(len(sig)), key.key) {
- return errors.New("verifypkcs1v15: failed to finalize verify")
- }
- return nil
-}
-
-func (key *pKey) MarshalPKCS1PrivateKeyPEM() (pem_block []byte,
- err error) {
- bio := C.BIO_new(C.BIO_s_mem())
- if bio == nil {
- return nil, errors.New("failed to allocate memory BIO")
- }
- defer C.BIO_free(bio)
- rsa := (*C.RSA)(C.EVP_PKEY_get1_RSA(key.key))
- if rsa == nil {
- return nil, errors.New("failed getting rsa key")
- }
- defer C.RSA_free(rsa)
- if int(C.PEM_write_bio_RSAPrivateKey(bio, rsa, nil, nil, C.int(0), nil,
- nil)) != 1 {
- return nil, errors.New("failed dumping private key")
- }
- return ioutil.ReadAll(asAnyBio(bio))
-}
-
-func (key *pKey) MarshalPKCS1PrivateKeyDER() (der_block []byte,
- err error) {
- bio := C.BIO_new(C.BIO_s_mem())
- if bio == nil {
- return nil, errors.New("failed to allocate memory BIO")
- }
- defer C.BIO_free(bio)
- rsa := (*C.RSA)(C.EVP_PKEY_get1_RSA(key.key))
- if rsa == nil {
- return nil, errors.New("failed getting rsa key")
- }
- defer C.RSA_free(rsa)
- if int(C.i2d_RSAPrivateKey_bio(bio, rsa)) != 1 {
- return nil, errors.New("failed dumping private key der")
- }
- return ioutil.ReadAll(asAnyBio(bio))
-}
-
-func (key *pKey) MarshalPKIXPublicKeyPEM() (pem_block []byte,
- err error) {
- bio := C.BIO_new(C.BIO_s_mem())
- if bio == nil {
- return nil, errors.New("failed to allocate memory BIO")
- }
- defer C.BIO_free(bio)
- rsa := (*C.RSA)(C.EVP_PKEY_get1_RSA(key.key))
- if rsa == nil {
- return nil, errors.New("failed getting rsa key")
- }
- defer C.RSA_free(rsa)
- if int(C.PEM_write_bio_RSA_PUBKEY(bio, rsa)) != 1 {
- return nil, errors.New("failed dumping public key pem")
- }
- return ioutil.ReadAll(asAnyBio(bio))
-}
-
-func (key *pKey) MarshalPKIXPublicKeyDER() (der_block []byte,
- err error) {
- bio := C.BIO_new(C.BIO_s_mem())
- if bio == nil {
- return nil, errors.New("failed to allocate memory BIO")
- }
- defer C.BIO_free(bio)
- rsa := (*C.RSA)(C.EVP_PKEY_get1_RSA(key.key))
- if rsa == nil {
- return nil, errors.New("failed getting rsa key")
- }
- defer C.RSA_free(rsa)
- if int(C.i2d_RSA_PUBKEY_bio(bio, rsa)) != 1 {
- return nil, errors.New("failed dumping public key der")
- }
- return ioutil.ReadAll(asAnyBio(bio))
-}
-
-// LoadPrivateKeyFromPEM loads a private key from a PEM-encoded block.
-func LoadPrivateKeyFromPEM(pem_block []byte) (PrivateKey, error) {
- if len(pem_block) == 0 {
- return nil, errors.New("empty pem block")
- }
- bio := C.BIO_new_mem_buf(unsafe.Pointer(&pem_block[0]),
- C.int(len(pem_block)))
- if bio == nil {
- return nil, errors.New("failed creating bio")
- }
- defer C.BIO_free(bio)
-
- rsakey := C.PEM_read_bio_RSAPrivateKey(bio, nil, nil, nil)
- if rsakey == nil {
- return nil, errors.New("failed reading rsa key")
- }
- defer C.RSA_free(rsakey)
-
- // convert to PKEY
- key := C.EVP_PKEY_new()
- if key == nil {
- return nil, errors.New("failed converting to evp_pkey")
- }
- if C.EVP_PKEY_set1_RSA(key, (*C.struct_rsa_st)(rsakey)) != 1 {
- C.EVP_PKEY_free(key)
- return nil, errors.New("failed converting to evp_pkey")
- }
-
- p := &pKey{key: key}
- runtime.SetFinalizer(p, func(p *pKey) {
- C.EVP_PKEY_free(p.key)
- })
- return p, nil
-}
-
-// LoadPublicKeyFromPEM loads a public key from a PEM-encoded block.
-func LoadPublicKeyFromPEM(pem_block []byte) (PublicKey, error) {
- if len(pem_block) == 0 {
- return nil, errors.New("empty pem block")
- }
- bio := C.BIO_new_mem_buf(unsafe.Pointer(&pem_block[0]),
- C.int(len(pem_block)))
- if bio == nil {
- return nil, errors.New("failed creating bio")
- }
- defer C.BIO_free(bio)
-
- rsakey := C.PEM_read_bio_RSA_PUBKEY(bio, nil, nil, nil)
- if rsakey == nil {
- return nil, errors.New("failed reading rsa key")
- }
- defer C.RSA_free(rsakey)
-
- // convert to PKEY
- key := C.EVP_PKEY_new()
- if key == nil {
- return nil, errors.New("failed converting to evp_pkey")
- }
- if C.EVP_PKEY_set1_RSA(key, (*C.struct_rsa_st)(rsakey)) != 1 {
- C.EVP_PKEY_free(key)
- return nil, errors.New("failed converting to evp_pkey")
- }
-
- p := &pKey{key: key}
- runtime.SetFinalizer(p, func(p *pKey) {
- C.EVP_PKEY_free(p.key)
- })
- return p, nil
-}
-
-// LoadPublicKeyFromDER loads a public key from a DER-encoded block.
-func LoadPublicKeyFromDER(der_block []byte) (PublicKey, error) {
- if len(der_block) == 0 {
- return nil, errors.New("empty der block")
- }
- bio := C.BIO_new_mem_buf(unsafe.Pointer(&der_block[0]),
- C.int(len(der_block)))
- if bio == nil {
- return nil, errors.New("failed creating bio")
- }
- defer C.BIO_free(bio)
-
- rsakey := C.d2i_RSA_PUBKEY_bio(bio, nil)
- if rsakey == nil {
- return nil, errors.New("failed reading rsa key")
- }
- defer C.RSA_free(rsakey)
-
- // convert to PKEY
- key := C.EVP_PKEY_new()
- if key == nil {
- return nil, errors.New("failed converting to evp_pkey")
- }
- if C.EVP_PKEY_set1_RSA(key, (*C.struct_rsa_st)(rsakey)) != 1 {
- C.EVP_PKEY_free(key)
- return nil, errors.New("failed converting to evp_pkey")
- }
+var pemSplit *regexp.Regexp = regexp.MustCompile(`(?sm)` +
+ `(^-----[\s-]*?BEGIN.*?-----$` +
+ `.*?` +
+ `^-----[\s-]*?END.*?-----$)`)
- p := &pKey{key: key}
- runtime.SetFinalizer(p, func(p *pKey) {
- C.EVP_PKEY_free(p.key)
- })
- return p, nil
-}
-
-type Certificate struct {
- x *C.X509
- ref interface{}
-}
-
-// LoadCertificateFromPEM loads an X509 certificate from a PEM-encoded block.
-func LoadCertificateFromPEM(pem_block []byte) (*Certificate, error) {
- if len(pem_block) == 0 {
- return nil, errors.New("empty pem block")
- }
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
- bio := C.BIO_new_mem_buf(unsafe.Pointer(&pem_block[0]),
- C.int(len(pem_block)))
- cert := C.PEM_read_bio_X509(bio, nil, nil, nil)
- C.BIO_free(bio)
- if cert == nil {
- return nil, errorFromErrorQueue()
- }
- x := &Certificate{x: cert}
- runtime.SetFinalizer(x, func(x *Certificate) {
- C.X509_free(x.x)
- })
- return x, nil
-}
-
-// MarshalPEM converts the X509 certificate to PEM-encoded format
-func (c *Certificate) MarshalPEM() (pem_block []byte, err error) {
- bio := C.BIO_new(C.BIO_s_mem())
- if bio == nil {
- return nil, errors.New("failed to allocate memory BIO")
- }
- defer C.BIO_free(bio)
- if int(C.PEM_write_bio_X509(bio, c.x)) != 1 {
- return nil, errors.New("failed dumping certificate")
- }
- return ioutil.ReadAll(asAnyBio(bio))
-}
-
-// PublicKey returns the public key embedded in the X509 certificate.
-func (c *Certificate) PublicKey() (PublicKey, error) {
- pkey := C.X509_get_pubkey(c.x)
- if pkey == nil {
- return nil, errors.New("no public key found")
- }
- key := &pKey{key: pkey}
- runtime.SetFinalizer(key, func(key *pKey) {
- C.EVP_PKEY_free(key.key)
- })
- return key, nil
-}
-
-// GetSerialNumberHex returns the certificate's serial number in hex format
-func (c *Certificate) GetSerialNumberHex() (serial string) {
- asn1_i := C.X509_get_serialNumber(c.x)
- bignum := C.ASN1_INTEGER_to_BN(asn1_i, nil)
- hex := C.BN_bn2hex(bignum)
- serial = C.GoString(hex)
- C.BN_free(bignum)
- C.OPENSSL_free_not_a_macro(unsafe.Pointer(hex))
- return
-}
-
-func (c *Certificate) X509NamePrintEx() (out []byte, err error) {
- bio := C.BIO_new(C.BIO_s_mem())
- if bio == nil {
- return nil, errors.New("failed to allocate memory BIO")
- }
- defer C.BIO_free(bio)
- name := C.X509_get_subject_name(c.x)
- // TODO, pass in flags instead of using this hardcoded one
- if int(C.X509_NAME_print_ex(bio, name, 0, C.XN_FLAG_RFC2253)) < 0 {
- return nil, errors.New("failed formatting subject")
+func SplitPEM(data []byte) [][]byte {
+ var results [][]byte
+ for _, block := range pemSplit.FindAll(data, -1) {
+ results = append(results, block)
}
- return ioutil.ReadAll(asAnyBio(bio))
+ return results
}
diff --git a/vendor/src/github.com/spacemonkeygo/openssl/sni.c b/vendor/src/github.com/spacemonkeygo/openssl/sni.c
new file mode 100644
index 00000000000..5398da869b8
--- /dev/null
+++ b/vendor/src/github.com/spacemonkeygo/openssl/sni.c
@@ -0,0 +1,23 @@
+// Copyright (C) 2014 Space Monkey, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <openssl/ssl.h>
+#include "_cgo_export.h"
+#include <stdio.h>
+
+int sni_cb(SSL *con, int *ad, void *arg) {
+ SSL_CTX* ssl_ctx = ssl_ctx = SSL_get_SSL_CTX(con);
+ void* p = SSL_CTX_get_ex_data(ssl_ctx, get_ssl_ctx_idx());
+ return sni_cb_thunk(p, con, ad, arg);
+}
diff --git a/vendor/src/github.com/spacemonkeygo/openssl/sni_test.go b/vendor/src/github.com/spacemonkeygo/openssl/sni_test.go
new file mode 100644
index 00000000000..ee3b1a8bbaf
--- /dev/null
+++ b/vendor/src/github.com/spacemonkeygo/openssl/sni_test.go
@@ -0,0 +1,23 @@
+// Copyright (C) 2014 Space Monkey, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package openssl
+
+import "fmt"
+
+// We can implemant SNI rfc6066 (http://tools.ietf.org/html/rfc6066) on the server side using foolowing callback.
+// You should implement context storage (tlsCtxStorage) by your self.
+func ExampleSetTLSExtServernameCallback() {
+ fmt.Println("Hello")
+}
diff --git a/vendor/src/github.com/spacemonkeygo/openssl/ssl.go b/vendor/src/github.com/spacemonkeygo/openssl/ssl.go
new file mode 100644
index 00000000000..d6120e15d99
--- /dev/null
+++ b/vendor/src/github.com/spacemonkeygo/openssl/ssl.go
@@ -0,0 +1,167 @@
+// Copyright (C) 2014 Space Monkey, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build cgo
+
+package openssl
+
+/*
+#include <openssl/crypto.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/conf.h>
+
+static long SSL_set_options_not_a_macro(SSL* ssl, long options) {
+ return SSL_set_options(ssl, options);
+}
+
+static long SSL_get_options_not_a_macro(SSL* ssl) {
+ return SSL_get_options(ssl);
+}
+
+static long SSL_clear_options_not_a_macro(SSL* ssl, long options) {
+ return SSL_clear_options(ssl, options);
+}
+
+extern int verify_ssl_cb(int ok, X509_STORE_CTX* store);
+*/
+import "C"
+
+import (
+ "os"
+ "unsafe"
+)
+
+type SSLTLSExtErr int
+
+var (
+ ssl_idx = C.SSL_get_ex_new_index(0, nil, nil, nil, nil)
+)
+
+//export get_ssl_idx
+func get_ssl_idx() C.int {
+ return ssl_idx
+}
+
+type SSL struct {
+ ssl *C.SSL
+ verify_cb VerifyCallback
+}
+
+//export verify_ssl_cb_thunk
+func verify_ssl_cb_thunk(p unsafe.Pointer, ok C.int, ctx *C.X509_STORE_CTX) C.int {
+ defer func() {
+ if err := recover(); err != nil {
+ logger.Critf("openssl: verify callback panic'd: %v", err)
+ os.Exit(1)
+ }
+ }()
+ verify_cb := (*SSL)(p).verify_cb
+ // set up defaults just in case verify_cb is nil
+ if verify_cb != nil {
+ store := &CertificateStoreCtx{ctx: ctx}
+ if verify_cb(ok == 1, store) {
+ ok = 1
+ } else {
+ ok = 0
+ }
+ }
+ return ok
+}
+
+// GetOptions returns SSL options. See
+// https://www.openssl.org/docs/ssl/SSL_CTX_set_options.html
+func (s *SSL) GetOptions() Options {
+ return Options(C.SSL_get_options_not_a_macro(s.ssl))
+}
+
+// SetOptions sets SSL options. See
+// https://www.openssl.org/docs/ssl/SSL_CTX_set_options.html
+func (s *SSL) SetOptions(options Options) Options {
+ return Options(C.SSL_set_options_not_a_macro(s.ssl, C.long(options)))
+}
+
+// ClearOptions clear SSL options. See
+// https://www.openssl.org/docs/ssl/SSL_CTX_set_options.html
+func (s *SSL) ClearOptions(options Options) Options {
+ return Options(C.SSL_clear_options_not_a_macro(s.ssl, C.long(options)))
+}
+
+// SetVerify controls peer verification settings. See
+// http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html
+func (s *SSL) SetVerify(options VerifyOptions, verify_cb VerifyCallback) {
+ s.verify_cb = verify_cb
+ if verify_cb != nil {
+ C.SSL_set_verify(s.ssl, C.int(options), (*[0]byte)(C.verify_ssl_cb))
+ } else {
+ C.SSL_set_verify(s.ssl, C.int(options), nil)
+ }
+}
+
+// SetVerifyMode controls peer verification setting. See
+// http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html
+func (s *SSL) SetVerifyMode(options VerifyOptions) {
+ s.SetVerify(options, s.verify_cb)
+}
+
+// SetVerifyCallback controls peer verification setting. See
+// http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html
+func (s *SSL) SetVerifyCallback(verify_cb VerifyCallback) {
+ s.SetVerify(s.VerifyMode(), s.verify_cb)
+}
+
+// GetVerifyCallback returns callback function. See
+// http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html
+func (s *SSL) GetVerifyCallback() VerifyCallback {
+ return s.verify_cb
+}
+
+// VerifyMode returns peer verification setting. See
+// http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html
+func (s *SSL) VerifyMode() VerifyOptions {
+ return VerifyOptions(C.SSL_get_verify_mode(s.ssl))
+}
+
+// SetVerifyDepth controls how many certificates deep the certificate
+// verification logic is willing to follow a certificate chain. See
+// https://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html
+func (s *SSL) SetVerifyDepth(depth int) {
+ C.SSL_set_verify_depth(s.ssl, C.int(depth))
+}
+
+// GetVerifyDepth controls how many certificates deep the certificate
+// verification logic is willing to follow a certificate chain. See
+// https://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html
+func (s *SSL) GetVerifyDepth() int {
+ return int(C.SSL_get_verify_depth(s.ssl))
+}
+
+//export sni_cb_thunk
+func sni_cb_thunk(p unsafe.Pointer, con *C.SSL, ad unsafe.Pointer, arg unsafe.Pointer) C.int {
+ defer func() {
+ if err := recover(); err != nil {
+ logger.Critf("openssl: verify callback sni panic'd: %v", err)
+ os.Exit(1)
+ }
+ }()
+
+ sni_cb := (*Ctx)(p).sni_cb
+
+ s := &SSL{ssl: con}
+ // This attaches a pointer to our SSL struct into the SNI callback.
+ C.SSL_set_ex_data(s.ssl, get_ssl_idx(), unsafe.Pointer(s))
+
+ // Note: this is ctx.sni_cb, not C.sni_cb
+ return C.int(sni_cb(s))
+}
diff --git a/vendor/src/github.com/spacemonkeygo/openssl/verify.c b/vendor/src/github.com/spacemonkeygo/openssl/verify.c
index bfc626812cd..d55866c4cf0 100644
--- a/vendor/src/github.com/spacemonkeygo/openssl/verify.c
+++ b/vendor/src/github.com/spacemonkeygo/openssl/verify.c
@@ -14,12 +14,18 @@
#include <openssl/ssl.h>
#include "_cgo_export.h"
-#include <stdio.h>
int verify_cb(int ok, X509_STORE_CTX* store) {
SSL* ssl = (SSL *)X509_STORE_CTX_get_app_data(store);
- SSL_CTX* ssl_ctx = ssl_ctx = SSL_get_SSL_CTX(ssl);
+ SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(ssl);
void* p = SSL_CTX_get_ex_data(ssl_ctx, get_ssl_ctx_idx());
// get the pointer to the go Ctx object and pass it back into the thunk
return verify_cb_thunk(p, ok, store);
}
+
+int verify_ssl_cb(int ok, X509_STORE_CTX* store) {
+ SSL* ssl = (SSL *)X509_STORE_CTX_get_app_data(store);
+ void* p = SSL_get_ex_data(ssl, get_ssl_idx());
+ // get the pointer to the go Ctx object and pass it back into the thunk
+ return verify_ssl_cb_thunk(p, ok, store);
+}