openssl 1.1.x support

- created a uniform shim layer for the Go code to invoke that does the
  right thing depending on the version of openssl. functions that have
  yet to be moved can be done so as needed.

- fixed the incorrect use of X509_STORE_CTX_get_app_data in verify_cb to
  pull out the SSL object from the x509 store context, which causes
  crashes when the SSL object index happens to not be zero.

- fix engine not being passed to HMAC_Init_ex

- fix HMAC tests not checking for failures with NewHMAC
This commit is contained in:
Andrew Harding 2017-06-02 08:47:50 -06:00 committed by Jeff
parent 28dd155517
commit b90544c9b0
25 changed files with 1053 additions and 736 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
openssl.test

106
bio.go
View File

@ -16,52 +16,7 @@
package openssl
/*
#include <string.h>
#include <openssl/bio.h>
extern int cbioNew(BIO *b);
static int cbioFree(BIO *b) {
return 1;
}
extern int writeBioWrite(BIO *b, char *buf, int size);
extern long writeBioCtrl(BIO *b, int cmd, long arg1, void *arg2);
static int writeBioPuts(BIO *b, const char *str) {
return writeBioWrite(b, (char*)str, (int)strlen(str));
}
extern int readBioRead(BIO *b, char *buf, int size);
extern long readBioCtrl(BIO *b, int cmd, long arg1, void *arg2);
static BIO_METHOD writeBioMethod = {
BIO_TYPE_SOURCE_SINK,
"Go Write BIO",
(int (*)(BIO *, const char *, int))writeBioWrite,
NULL,
writeBioPuts,
NULL,
writeBioCtrl,
cbioNew,
cbioFree,
NULL};
static BIO_METHOD* BIO_s_writeBio() { return &writeBioMethod; }
static BIO_METHOD readBioMethod = {
BIO_TYPE_SOURCE_SINK,
"Go Read BIO",
NULL,
readBioRead,
NULL,
NULL,
readBioCtrl,
cbioNew,
cbioFree,
NULL};
static BIO_METHOD* BIO_s_readBio() { return &readBioMethod; }
*/
// #include "shim.h"
import "C"
import (
@ -89,16 +44,6 @@ func nonCopyCString(data *C.char, size C.int) []byte {
return nonCopyGoBytes(uintptr(unsafe.Pointer(data)), int(size))
}
//export cbioNew
func cbioNew(b *C.BIO) C.int {
b.shutdown = 1
b.init = 1
b.num = -1
b.ptr = nil
b.flags = 0
return 1
}
var writeBioMapping = newMapping()
type writeBio struct {
@ -109,21 +54,20 @@ type writeBio struct {
}
func loadWritePtr(b *C.BIO) *writeBio {
return (*writeBio)(writeBioMapping.Get(token(b.ptr)))
t := token(C.X_BIO_get_data(b))
return (*writeBio)(writeBioMapping.Get(t))
}
func bioClearRetryFlags(b *C.BIO) {
// from BIO_clear_retry_flags and BIO_clear_flags
b.flags &= ^(C.BIO_FLAGS_RWS | C.BIO_FLAGS_SHOULD_RETRY)
C.X_BIO_clear_flags(b, C.BIO_FLAGS_RWS|C.BIO_FLAGS_SHOULD_RETRY)
}
func bioSetRetryRead(b *C.BIO) {
// from BIO_set_retry_read and BIO_set_flags
b.flags |= (C.BIO_FLAGS_READ | C.BIO_FLAGS_SHOULD_RETRY)
C.X_BIO_set_flags(b, C.BIO_FLAGS_READ|C.BIO_FLAGS_SHOULD_RETRY)
}
//export writeBioWrite
func writeBioWrite(b *C.BIO, data *C.char, size C.int) (rc C.int) {
//export go_write_bio_write
func go_write_bio_write(b *C.BIO, data *C.char, size C.int) (rc C.int) {
defer func() {
if err := recover(); err != nil {
logger.Critf("openssl: writeBioWrite panic'd: %v", err)
@ -141,8 +85,8 @@ func writeBioWrite(b *C.BIO, data *C.char, size C.int) (rc C.int) {
return size
}
//export writeBioCtrl
func writeBioCtrl(b *C.BIO, cmd C.int, arg1 C.long, arg2 unsafe.Pointer) (
//export go_write_bio_ctrl
func go_write_bio_ctrl(b *C.BIO, cmd C.int, arg1 C.long, arg2 unsafe.Pointer) (
rc C.long) {
defer func() {
if err := recover(); err != nil {
@ -197,15 +141,15 @@ func (b *writeBio) WriteTo(w io.Writer) (rv int64, err error) {
func (self *writeBio) Disconnect(b *C.BIO) {
if loadWritePtr(b) == self {
writeBioMapping.Del(token(b.ptr))
b.ptr = nil
writeBioMapping.Del(token(C.X_BIO_get_data(b)))
C.X_BIO_set_data(b, nil)
}
}
func (b *writeBio) MakeCBIO() *C.BIO {
rv := C.BIO_new(C.BIO_s_writeBio())
rv := C.X_BIO_new_write_bio()
token := writeBioMapping.Add(unsafe.Pointer(b))
rv.ptr = unsafe.Pointer(token)
C.X_BIO_set_data(rv, unsafe.Pointer(token))
return rv
}
@ -220,14 +164,14 @@ type readBio struct {
}
func loadReadPtr(b *C.BIO) *readBio {
return (*readBio)(readBioMapping.Get(token(b.ptr)))
return (*readBio)(readBioMapping.Get(token(C.X_BIO_get_data(b))))
}
//export readBioRead
func readBioRead(b *C.BIO, data *C.char, size C.int) (rc C.int) {
//export go_read_bio_read
func go_read_bio_read(b *C.BIO, data *C.char, size C.int) (rc C.int) {
defer func() {
if err := recover(); err != nil {
logger.Critf("openssl: readBioRead panic'd: %v", err)
logger.Critf("openssl: go_read_bio_read panic'd: %v", err)
rc = -1
}
}()
@ -256,8 +200,8 @@ func readBioRead(b *C.BIO, data *C.char, size C.int) (rc C.int) {
return C.int(n)
}
//export readBioCtrl
func readBioCtrl(b *C.BIO, cmd C.int, arg1 C.long, arg2 unsafe.Pointer) (
//export go_read_bio_ctrl
func go_read_bio_ctrl(b *C.BIO, cmd C.int, arg1 C.long, arg2 unsafe.Pointer) (
rc C.long) {
defer func() {
@ -316,16 +260,16 @@ func (b *readBio) ReadFromOnce(r io.Reader) (n int, err error) {
}
func (b *readBio) MakeCBIO() *C.BIO {
rv := C.BIO_new(C.BIO_s_readBio())
rv := C.X_BIO_new_read_bio()
token := readBioMapping.Add(unsafe.Pointer(b))
rv.ptr = unsafe.Pointer(token)
C.X_BIO_set_data(rv, unsafe.Pointer(token))
return rv
}
func (self *readBio) Disconnect(b *C.BIO) {
if loadReadPtr(b) == self {
readBioMapping.Del(token(b.ptr))
b.ptr = nil
readBioMapping.Del(token(C.X_BIO_get_data(b)))
C.X_BIO_set_data(b, nil)
}
}
@ -343,7 +287,7 @@ func (b *anyBio) Read(buf []byte) (n int, err error) {
if len(buf) == 0 {
return 0, nil
}
n = int(C.BIO_read((*C.BIO)(b), unsafe.Pointer(&buf[0]), C.int(len(buf))))
n = int(C.X_BIO_read((*C.BIO)(b), unsafe.Pointer(&buf[0]), C.int(len(buf))))
if n <= 0 {
return 0, io.EOF
}
@ -354,7 +298,7 @@ func (b *anyBio) Write(buf []byte) (written int, err error) {
if len(buf) == 0 {
return 0, nil
}
n := int(C.BIO_write((*C.BIO)(b), unsafe.Pointer(&buf[0]),
n := int(C.X_BIO_write((*C.BIO)(b), unsafe.Pointer(&buf[0]),
C.int(len(buf))))
if n != len(buf) {
return n, errors.New("BIO write failed")

View File

@ -17,7 +17,8 @@
package openssl
// #cgo pkg-config: libssl libcrypto
// #cgo linux CFLAGS: -Wno-deprecated-declarations
// #cgo darwin CFLAGS: -I/usr/local/opt/openssl@1.1/include -I/usr/local/opt/openssl/include -Wno-deprecated-declarations
// #cgo darwin LDFLAGS: -L/usr/local/opt/openssl@1.1/lib -L/usr/local/opt/openssl/lib
// #cgo windows CFLAGS: -DWIN32_LEAN_AND_MEAN
// #cgo darwin CFLAGS: -Wno-deprecated-declarations -I/usr/local/opt/openssl/include
// #cgo darwin LDFLAGS: -L/usr/local/opt/openssl/lib
import "C"

37
cert.go
View File

@ -16,12 +16,7 @@
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); }
//
// #include "shim.h"
import "C"
import (
@ -229,7 +224,7 @@ func (c *Certificate) SetSerial(serial *big.Int) error {
// 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)
result := C.X509_gmtime_adj(C.X_X509_get0_notBefore(c.x), offset)
if result == nil {
return errors.New("failed to set issue date")
}
@ -239,7 +234,7 @@ func (c *Certificate) SetIssueDate(when time.Duration) error {
// 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)
result := C.X509_gmtime_adj(C.X_X509_get0_notAfter(c.x), offset)
if result == nil {
return errors.New("failed to set expire date")
}
@ -281,30 +276,30 @@ func getDigestFunction(digest EVP_MD) (md *C.EVP_MD) {
switch digest {
// please don't use these digest functions
case EVP_NULL:
md = C.EVP_md_null()
md = C.X_EVP_md_null()
case EVP_MD5:
md = C.EVP_md5()
md = C.X_EVP_md5()
case EVP_SHA:
md = C.EVP_sha()
md = C.X_EVP_sha()
case EVP_SHA1:
md = C.EVP_sha1()
md = C.X_EVP_sha1()
case EVP_DSS:
md = C.EVP_dss()
md = C.X_EVP_dss()
case EVP_DSS1:
md = C.EVP_dss1()
md = C.X_EVP_dss1()
case EVP_RIPEMD160:
md = C.EVP_ripemd160()
md = C.X_EVP_ripemd160()
case EVP_SHA224:
md = C.EVP_sha224()
md = C.X_EVP_sha224()
// you actually want one of these
case EVP_SHA256:
md = C.EVP_sha256()
md = C.X_EVP_sha256()
case EVP_SHA384:
md = C.EVP_sha384()
md = C.X_EVP_sha384()
case EVP_SHA512:
md = C.EVP_sha512()
md = C.X_EVP_sha512()
}
return
return md
}
// Add an extension to a certificate.
@ -392,6 +387,6 @@ func (c *Certificate) GetSerialNumberHex() (serial string) {
hex := C.BN_bn2hex(bignum)
serial = C.GoString(hex)
C.BN_free(bignum)
C.OPENSSL_free_not_a_macro(unsafe.Pointer(hex))
C.X_OPENSSL_free(unsafe.Pointer(hex))
return
}

View File

@ -16,39 +16,7 @@
package openssl
// #include <openssl/evp.h>
//
// int EVP_CIPHER_block_size_not_a_macro(EVP_CIPHER *c) {
// return EVP_CIPHER_block_size(c);
// }
//
// int EVP_CIPHER_key_length_not_a_macro(EVP_CIPHER *c) {
// return EVP_CIPHER_key_length(c);
// }
//
// int EVP_CIPHER_iv_length_not_a_macro(EVP_CIPHER *c) {
// return EVP_CIPHER_iv_length(c);
// }
//
// int EVP_CIPHER_nid_not_a_macro(EVP_CIPHER *c) {
// return EVP_CIPHER_nid(c);
// }
//
// int EVP_CIPHER_CTX_block_size_not_a_macro(EVP_CIPHER_CTX *ctx) {
// return EVP_CIPHER_CTX_block_size(ctx);
// }
//
// int EVP_CIPHER_CTX_key_length_not_a_macro(EVP_CIPHER_CTX *ctx) {
// return EVP_CIPHER_CTX_key_length(ctx);
// }
//
// int EVP_CIPHER_CTX_iv_length_not_a_macro(EVP_CIPHER_CTX *ctx) {
// return EVP_CIPHER_CTX_iv_length(ctx);
// }
//
// const EVP_CIPHER *EVP_CIPHER_CTX_cipher_not_a_macro(EVP_CIPHER_CTX *ctx) {
// return EVP_CIPHER_CTX_cipher(ctx);
// }
// #include "shim.h"
import "C"
import (
@ -74,7 +42,7 @@ type Cipher struct {
}
func (c *Cipher) Nid() NID {
return NID(C.EVP_CIPHER_nid_not_a_macro(c.ptr))
return NID(C.X_EVP_CIPHER_nid(c.ptr))
}
func (c *Cipher) ShortName() (string, error) {
@ -82,15 +50,15 @@ func (c *Cipher) ShortName() (string, error) {
}
func (c *Cipher) BlockSize() int {
return int(C.EVP_CIPHER_block_size_not_a_macro(c.ptr))
return int(C.X_EVP_CIPHER_block_size(c.ptr))
}
func (c *Cipher) KeySize() int {
return int(C.EVP_CIPHER_key_length_not_a_macro(c.ptr))
return int(C.X_EVP_CIPHER_key_length(c.ptr))
}
func (c *Cipher) IVSize() int {
return int(C.EVP_CIPHER_iv_length_not_a_macro(c.ptr))
return int(C.X_EVP_CIPHER_iv_length(c.ptr))
}
func Nid2ShortName(nid NID) (string, error) {
@ -154,7 +122,7 @@ func (ctx *cipherCtx) applyKeyAndIV(key, iv []byte) error {
}
if kptr != nil || iptr != nil {
var res C.int
if ctx.ctx.encrypt != 0 {
if C.X_EVP_CIPHER_CTX_encrypting(ctx.ctx) != 0 {
res = C.EVP_EncryptInit_ex(ctx.ctx, nil, nil, kptr, iptr)
} else {
res = C.EVP_DecryptInit_ex(ctx.ctx, nil, nil, kptr, iptr)
@ -167,19 +135,19 @@ func (ctx *cipherCtx) applyKeyAndIV(key, iv []byte) error {
}
func (ctx *cipherCtx) Cipher() *Cipher {
return &Cipher{ptr: C.EVP_CIPHER_CTX_cipher_not_a_macro(ctx.ctx)}
return &Cipher{ptr: C.X_EVP_CIPHER_CTX_cipher(ctx.ctx)}
}
func (ctx *cipherCtx) BlockSize() int {
return int(C.EVP_CIPHER_CTX_block_size_not_a_macro(ctx.ctx))
return int(C.X_EVP_CIPHER_CTX_block_size(ctx.ctx))
}
func (ctx *cipherCtx) KeySize() int {
return int(C.EVP_CIPHER_CTX_key_length_not_a_macro(ctx.ctx))
return int(C.X_EVP_CIPHER_CTX_key_length(ctx.ctx))
}
func (ctx *cipherCtx) IVSize() int {
return int(C.EVP_CIPHER_CTX_iv_length_not_a_macro(ctx.ctx))
return int(C.X_EVP_CIPHER_CTX_iv_length(ctx.ctx))
}
func (ctx *cipherCtx) setCtrl(code, arg int) error {

31
conn.go
View File

@ -16,26 +16,7 @@
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);
}
long SSL_set_tlsext_host_name_not_a_macro(SSL *ssl, const char *name) {
return SSL_set_tlsext_host_name(ssl, name);
}
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);
}
*/
// #include "shim.h"
import "C"
import (
@ -211,7 +192,7 @@ func Server(conn net.Conn, ctx *Ctx) (*Conn, error) {
func (c *Conn) GetCtx() *Ctx { return c.ctx }
func (c *Conn) CurrentCipher() (string, error) {
p := C.SSL_get_cipher_name_not_a_macro(c.ssl)
p := C.X_SSL_get_cipher_name(c.ssl)
if p == nil {
return "", errors.New("Session not established")
}
@ -356,10 +337,10 @@ func (c *Conn) PeerCertificate() (*Certificate, error) {
func (c *Conn) loadCertificateStack(sk *C.struct_stack_st_X509) (
rv []*Certificate) {
sk_num := int(C.sk_X509_num_not_a_macro(sk))
sk_num := int(C.X_sk_X509_num(sk))
rv = make([]*Certificate, 0, sk_num)
for i := 0; i < sk_num; i++ {
x := C.sk_X509_value_not_a_macro(sk, C.int(i))
x := C.X_sk_X509_value(sk, C.int(i))
// ref holds on to the underlying connection memory so we don't need to
// worry about incrementing refcounts manually or freeing the X509
rv = append(rv, &Certificate{x: x, ref: c})
@ -580,7 +561,7 @@ func (c *Conn) SetTlsExtHostName(name string) error {
defer C.free(unsafe.Pointer(cname))
runtime.LockOSThread()
defer runtime.UnlockOSThread()
if C.SSL_set_tlsext_host_name_not_a_macro(c.ssl, cname) == 0 {
if C.X_SSL_set_tlsext_host_name(c.ssl, cname) == 0 {
return errorFromErrorQueue()
}
return nil
@ -591,7 +572,7 @@ func (c *Conn) VerifyResult() VerifyResult {
}
func (c *Conn) SessionReused() bool {
return C.SSL_session_reused_not_a_macro(c.ssl) == 1
return C.X_SSL_session_reused(c.ssl) == 1
}
func (c *Conn) GetSession() ([]byte, error) {

142
ctx.go
View File

@ -16,99 +16,7 @@
package openssl
/*
#include <openssl/crypto.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/conf.h>
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);
}
static long SSL_CTX_get_mode_not_a_macro(SSL_CTX* ctx) {
return SSL_CTX_get_mode(ctx);
}
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);
}
static long SSL_CTX_add_extra_chain_cert_not_a_macro(SSL_CTX* ctx, X509 *cert) {
return SSL_CTX_add_extra_chain_cert(ctx, cert);
}
static long SSL_CTX_set_tmp_ecdh_not_a_macro(SSL_CTX* ctx, EC_KEY *key) {
return SSL_CTX_set_tmp_ecdh(ctx, key);
}
static long SSL_CTX_set_tlsext_servername_callback_not_a_macro(
SSL_CTX* ctx, int (*cb)(SSL *con, int *ad, void *args)) {
return SSL_CTX_set_tlsext_servername_callback(ctx, cb);
}
#ifndef SSL_MODE_RELEASE_BUFFERS
#define SSL_MODE_RELEASE_BUFFERS 0
#endif
#ifndef SSL_OP_NO_COMPRESSION
#define SSL_OP_NO_COMPRESSION 0
#endif
static const SSL_METHOD *OUR_TLSv1_1_method() {
#if defined(TLS1_1_VERSION) && !defined(OPENSSL_SYSNAME_MACOSX)
return TLSv1_1_method();
#else
return NULL;
#endif
}
static const SSL_METHOD *OUR_TLSv1_2_method() {
#if 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);
*/
// #include "shim.h"
import "C"
import (
@ -125,7 +33,7 @@ import (
)
var (
ssl_ctx_idx = C.SSL_CTX_get_ex_new_index(0, nil, nil, nil, nil)
ssl_ctx_idx = C.X_SSL_CTX_new_index()
logger = spacelog.GetLogger()
)
@ -181,15 +89,15 @@ func NewCtxWithVersion(version SSLVersion) (*Ctx, error) {
var method *C.SSL_METHOD
switch version {
case SSLv3:
method = C.SSLv3_method()
method = C.X_SSLv3_method()
case TLSv1:
method = C.TLSv1_method()
method = C.X_TLSv1_method()
case TLSv1_1:
method = C.OUR_TLSv1_1_method()
method = C.X_TLSv1_1_method()
case TLSv1_2:
method = C.OUR_TLSv1_2_method()
method = C.X_TLSv1_2_method()
case AnyVersion:
method = C.SSLv23_method()
method = C.X_SSLv23_method()
}
if method == nil {
return nil, errors.New("unknown ssl/tls version")
@ -286,7 +194,7 @@ func (c *Ctx) SetEllipticCurve(curve EllipticCurve) error {
}
defer C.EC_KEY_free(k)
if int(C.SSL_CTX_set_tmp_ecdh_not_a_macro(c.ctx, k)) != 1 {
if int(C.X_SSL_CTX_set_tmp_ecdh(c.ctx, k)) != 1 {
return errorFromErrorQueue()
}
@ -311,7 +219,7 @@ 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 {
if int(C.X_SSL_CTX_add_extra_chain_cert(c.ctx, cert.x)) != 1 {
return errorFromErrorQueue()
}
// OpenSSL takes ownership via SSL_CTX_add_extra_chain_cert
@ -419,7 +327,9 @@ func (self *CertificateStoreCtx) GetCurrentCert() *Certificate {
return nil
}
// add a ref
C.CRYPTO_add_not_a_macro(&x509.references, 1, C.CRYPTO_LOCK_X509)
if 1 != C.X_X509_add_ref(x509) {
return nil
}
cert := &Certificate{
x: x509,
}
@ -467,19 +377,19 @@ const (
// SetOptions sets context options. See
// http://www.openssl.org/docs/ssl/SSL_CTX_set_options.html
func (c *Ctx) SetOptions(options Options) Options {
return Options(C.SSL_CTX_set_options_not_a_macro(
return Options(C.X_SSL_CTX_set_options(
c.ctx, C.long(options)))
}
func (c *Ctx) ClearOptions(options Options) Options {
return Options(C.SSL_CTX_clear_options_not_a_macro(
return Options(C.X_SSL_CTX_clear_options(
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))
return Options(C.X_SSL_CTX_get_options(c.ctx))
}
type Modes int
@ -492,13 +402,13 @@ const (
// SetMode sets context modes. See
// http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html
func (c *Ctx) SetMode(modes Modes) Modes {
return Modes(C.SSL_CTX_set_mode_not_a_macro(c.ctx, C.long(modes)))
return Modes(C.X_SSL_CTX_set_mode(c.ctx, C.long(modes)))
}
// GetMode returns context modes. See
// http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html
func (c *Ctx) GetMode() Modes {
return Modes(C.SSL_CTX_get_mode_not_a_macro(c.ctx))
return Modes(C.X_SSL_CTX_get_mode(c.ctx))
}
type VerifyOptions int
@ -512,8 +422,8 @@ const (
type VerifyCallback func(ok bool, store *CertificateStoreCtx) bool
//export verify_cb_thunk
func verify_cb_thunk(p unsafe.Pointer, ok C.int, ctx *C.X509_STORE_CTX) C.int {
//export go_ssl_ctx_verify_cb_thunk
func go_ssl_ctx_verify_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)
@ -538,7 +448,7 @@ func verify_cb_thunk(p unsafe.Pointer, ok C.int, ctx *C.X509_STORE_CTX) C.int {
func (c *Ctx) SetVerify(options VerifyOptions, verify_cb VerifyCallback) {
c.verify_cb = verify_cb
if verify_cb != nil {
C.SSL_CTX_set_verify(c.ctx, C.int(options), (*[0]byte)(C.verify_cb))
C.SSL_CTX_set_verify(c.ctx, C.int(options), (*[0]byte)(C.X_SSL_CTX_verify_cb))
} else {
C.SSL_CTX_set_verify(c.ctx, C.int(options), nil)
}
@ -581,7 +491,7 @@ type TLSExtServernameCallback func(ssl *SSL) SSLTLSExtErr
// http://stackoverflow.com/questions/22373332/serving-multiple-domains-in-one-box-with-sni
func (c *Ctx) SetTLSExtServernameCallback(sni_cb TLSExtServernameCallback) {
c.sni_cb = sni_cb
C.SSL_CTX_set_tlsext_servername_callback_not_a_macro(c.ctx, (*[0]byte)(C.sni_cb))
C.X_SSL_CTX_set_tlsext_servername_callback(c.ctx, (*[0]byte)(C.sni_cb))
}
func (c *Ctx) SetSessionId(session_id []byte) error {
@ -629,30 +539,30 @@ const (
// http://www.openssl.org/docs/ssl/SSL_CTX_set_session_cache_mode.html
func (c *Ctx) SetSessionCacheMode(modes SessionCacheModes) SessionCacheModes {
return SessionCacheModes(
C.SSL_CTX_set_session_cache_mode_not_a_macro(c.ctx, C.long(modes)))
C.X_SSL_CTX_set_session_cache_mode(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))
prev := C.X_SSL_CTX_set_timeout(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
return time.Duration(C.X_SSL_CTX_get_timeout(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)))
return int(C.X_SSL_CTX_sess_set_cache_size(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))
return int(C.X_SSL_CTX_sess_get_cache_size(c.ctx))
}

View File

@ -2,20 +2,7 @@
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);
}
*/
// #include "shim.h"
import "C"
import (
@ -58,7 +45,7 @@ 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 {
if int(C.X_SSL_CTX_set_tmp_dh(c.ctx, dh.dh)) != 1 {
return errorFromErrorQueue()
}
return nil

View File

@ -16,7 +16,7 @@
package openssl
// #include <openssl/evp.h>
// #include "shim.h"
import "C"
import (
@ -34,7 +34,7 @@ type Digest struct {
func GetDigestByName(name string) (*Digest, error) {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
p := C.EVP_get_digestbyname(cname)
p := C.X_EVP_get_digestbyname(cname)
if p == nil {
return nil, fmt.Errorf("Digest %v not found", name)
}

56
hmac.go
View File

@ -16,24 +16,17 @@
package openssl
/*
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "openssl/evp.h"
#include "openssl/hmac.h"
*/
// #include "shim.h"
import "C"
import (
"errors"
"runtime"
"unsafe"
)
type HMAC struct {
ctx C.HMAC_CTX
ctx *C.HMAC_CTX
engine *Engine
md *C.EVP_MD
}
@ -44,38 +37,57 @@ func NewHMAC(key []byte, digestAlgorithm EVP_MD) (*HMAC, error) {
func NewHMACWithEngine(key []byte, digestAlgorithm EVP_MD, e *Engine) (*HMAC, error) {
var md *C.EVP_MD = getDigestFunction(digestAlgorithm)
hmac := &HMAC{engine: e, md: md}
C.HMAC_CTX_init(&hmac.ctx)
C.HMAC_Init_ex(&hmac.ctx,
h := &HMAC{engine: e, md: md}
h.ctx = C.X_HMAC_CTX_new()
if h.ctx == nil {
return nil, errors.New("unable to allocate HMAC_CTX")
}
var c_e *C.ENGINE
if e != nil {
c_e = e.e
}
if rc := C.X_HMAC_Init_ex(h.ctx,
unsafe.Pointer(&key[0]),
C.int(len(key)),
md,
nil)
c_e); rc != 1 {
C.X_HMAC_CTX_free(h.ctx)
return nil, errors.New("failed to initialize HMAC_CTX")
}
runtime.SetFinalizer(hmac, func(hmac *HMAC) { hmac.Close() })
return hmac, nil
runtime.SetFinalizer(h, func(h *HMAC) { h.Close() })
return h, nil
}
func (h *HMAC) Close() {
C.HMAC_CTX_cleanup(&h.ctx)
C.X_HMAC_CTX_free(h.ctx)
}
func (s *HMAC) Write(data []byte) (n int, err error) {
func (h *HMAC) Write(data []byte) (n int, err error) {
if len(data) == 0 {
return 0, nil
}
C.HMAC_Update(&s.ctx, (*C.uchar)(unsafe.Pointer(&data[0])), C.size_t(len(data)))
if rc := C.X_HMAC_Update(h.ctx, (*C.uchar)(unsafe.Pointer(&data[0])),
C.size_t(len(data))); rc != 1 {
return 0, errors.New("failed to update HMAC")
}
return len(data), nil
}
func (h *HMAC) Reset() error {
C.HMAC_Init_ex(&h.ctx, nil, 0, nil, nil)
if 1 != C.X_HMAC_Init_ex(h.ctx, nil, 0, nil, nil) {
return errors.New("failed to reset HMAC_CTX")
}
return nil
}
func (h *HMAC) Final() (result []byte, err error) {
mdLength := C.EVP_MD_size(h.md)
mdLength := C.X_EVP_MD_size(h.md)
result = make([]byte, mdLength)
C.HMAC_Final(&h.ctx, (*C.uchar)(unsafe.Pointer(&result[0])), (*C.uint)(unsafe.Pointer(&mdLength)))
if rc := C.X_HMAC_Final(h.ctx, (*C.uchar)(unsafe.Pointer(&result[0])),
(*C.uint)(unsafe.Pointer(&mdLength))); rc != 1 {
return nil, errors.New("failed to finalized HMAC")
}
return result, h.Reset()
}

View File

@ -26,10 +26,15 @@ import (
func TestSHA256HMAC(t *testing.T) {
key := []byte("d741787cc61851af045ccd37")
data := []byte("5912EEFD-59EC-43E3-ADB8-D5325AEC3271")
h, _ := NewHMAC(key, EVP_SHA256)
h.Write(data)
var err error
h, err := NewHMAC(key, EVP_SHA256)
if err != nil {
t.Fatalf("Unable to create new HMAC: %s", err)
}
if _, err := h.Write(data); err != nil {
t.Fatalf("Unable to write data into HMAC: %s", err)
}
var actualHMACBytes []byte
if actualHMACBytes, err = h.Final(); err != nil {
t.Fatalf("Error while finalizing HMAC: %s", err)
@ -47,10 +52,19 @@ func TestSHA256HMAC(t *testing.T) {
}
func BenchmarkSHA256HMAC(b *testing.B) {
h, _ := NewHMAC([]byte("d741787cc61851af045ccd37"), EVP_SHA256)
key := []byte("d741787cc61851af045ccd37")
data := []byte("5912EEFD-59EC-43E3-ADB8-D5325AEC3271")
h, err := NewHMAC(key, EVP_SHA256)
if err != nil {
b.Fatalf("Unable to create new HMAC: %s", err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
h.Write([]byte("5912EEFD-59EC-43E3-ADB8-D5325AEC3271"))
if _, err := h.Write(data); err != nil {
b.Fatalf("Unable to write data into HMAC: %s", err)
}
var err error
if _, err = h.Final(); err != nil {

View File

@ -67,6 +67,7 @@
*/
/* X509 v3 extension utilities */
#include <string.h>
#include <stdlib.h>
#include <openssl/ssl.h>
#include <openssl/conf.h>

37
init.go
View File

@ -86,32 +86,7 @@ supported the generality needed to use OpenSSL instead of crypto/tls.
*/
package openssl
/*
#include <openssl/ssl.h>
#include <openssl/conf.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/engine.h>
extern int Goopenssl_init_locks();
extern void Goopenssl_thread_locking_callback(int, int, const char*, int);
static int Goopenssl_init_threadsafety() {
// Set up OPENSSL thread safety callbacks. We only set the locking
// callback because the default id callback implementation is good
// enough for us.
int rc = Goopenssl_init_locks();
if (rc == 0) {
CRYPTO_set_locking_callback(Goopenssl_thread_locking_callback);
}
return rc;
}
static void OpenSSL_add_all_algorithms_not_a_macro() {
OpenSSL_add_all_algorithms();
}
*/
// #include "shim.h"
import "C"
import (
@ -121,14 +96,8 @@ import (
)
func init() {
C.OPENSSL_config(nil)
C.ENGINE_load_builtin_engines()
C.SSL_load_error_strings()
C.SSL_library_init()
C.OpenSSL_add_all_algorithms_not_a_macro()
rc := C.Goopenssl_init_threadsafety()
if rc != 0 {
panic(fmt.Errorf("Goopenssl_init_locks failed with %d", rc))
if rc := C.X_shim_init(); rc != 0 {
panic(fmt.Errorf("X_shim_init failed with %d", rc))
}
}

View File

@ -24,7 +24,7 @@ package openssl
pthread_mutex_t* goopenssl_locks;
int Goopenssl_init_locks() {
int go_init_locks() {
int rc = 0;
int nlock;
int i;
@ -52,7 +52,7 @@ int Goopenssl_init_locks() {
return rc;
}
void Goopenssl_thread_locking_callback(int mode, int n, const char *file,
void go_thread_locking_callback(int mode, int n, const char *file,
int line) {
if (mode & CRYPTO_LOCK) {
pthread_mutex_lock(&goopenssl_locks[n]);

View File

@ -29,7 +29,7 @@ package openssl
CRITICAL_SECTION* goopenssl_locks;
int Goopenssl_init_locks() {
int go_init_locks() {
int rc = 0;
int nlock;
int i;
@ -47,7 +47,7 @@ int Goopenssl_init_locks() {
return 0;
}
void Goopenssl_thread_locking_callback(int mode, int n, const char *file,
void go_thread_locking_callback(int mode, int n, const char *file,
int line) {
if (mode & CRYPTO_LOCK) {
EnterCriticalSection(&goopenssl_locks[n]);

116
key.go
View File

@ -16,31 +16,7 @@
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);
// }
// #include "shim.h"
import "C"
import (
@ -53,9 +29,9 @@ import (
type Method *C.EVP_MD
var (
SHA1_Method Method = C.EVP_sha1()
SHA256_Method Method = C.EVP_sha256()
SHA512_Method Method = C.EVP_sha512()
SHA1_Method Method = C.X_EVP_sha1()
SHA256_Method Method = C.X_EVP_sha256()
SHA512_Method Method = C.X_EVP_sha512()
)
type PublicKey interface {
@ -95,22 +71,21 @@ type pKey struct {
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)
ctx := C.X_EVP_MD_CTX_new()
defer C.X_EVP_MD_CTX_free(ctx)
if 1 != C.EVP_SignInit_not_a_macro(&ctx, method) {
if 1 != C.X_EVP_SignInit(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))) {
if 1 != C.X_EVP_SignUpdate(
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))
sig := make([]byte, C.X_EVP_PKEY_size(key.key))
var sigblen C.uint
if 1 != C.EVP_SignFinal(&ctx,
if 1 != C.X_EVP_SignFinal(ctx,
((*C.uchar)(unsafe.Pointer(&sig[0]))), &sigblen, key.key) {
return nil, errors.New("signpkcs1v15: failed to finalize signature")
}
@ -118,20 +93,19 @@ func (key *pKey) SignPKCS1v15(method Method, data []byte) ([]byte, error) {
}
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)
ctx := C.X_EVP_MD_CTX_new()
defer C.X_EVP_MD_CTX_free(ctx)
if 1 != C.EVP_VerifyInit_not_a_macro(&ctx, method) {
if 1 != C.X_EVP_VerifyInit(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))) {
if 1 != C.X_EVP_VerifyUpdate(
ctx, unsafe.Pointer(&data[0]), C.uint(len(data))) {
return errors.New("verifypkcs1v15: failed to update verify")
}
}
if 1 != C.EVP_VerifyFinal(&ctx,
if 1 != C.X_EVP_VerifyFinal(ctx,
((*C.uchar)(unsafe.Pointer(&sig[0]))), C.uint(len(sig)), key.key) {
return errors.New("verifypkcs1v15: failed to finalize verify")
}
@ -145,7 +119,7 @@ func (key *pKey) MarshalPKCS1PrivateKeyPEM() (pem_block []byte,
return nil, errors.New("failed to allocate memory BIO")
}
defer C.BIO_free(bio)
rsa := (*C.RSA)(C.EVP_PKEY_get1_RSA(key.key))
rsa := (*C.RSA)(C.X_EVP_PKEY_get1_RSA(key.key))
if rsa == nil {
return nil, errors.New("failed getting rsa key")
}
@ -164,7 +138,7 @@ func (key *pKey) MarshalPKCS1PrivateKeyDER() (der_block []byte,
return nil, errors.New("failed to allocate memory BIO")
}
defer C.BIO_free(bio)
rsa := (*C.RSA)(C.EVP_PKEY_get1_RSA(key.key))
rsa := (*C.RSA)(C.X_EVP_PKEY_get1_RSA(key.key))
if rsa == nil {
return nil, errors.New("failed getting rsa key")
}
@ -182,7 +156,7 @@ func (key *pKey) MarshalPKIXPublicKeyPEM() (pem_block []byte,
return nil, errors.New("failed to allocate memory BIO")
}
defer C.BIO_free(bio)
rsa := (*C.RSA)(C.EVP_PKEY_get1_RSA(key.key))
rsa := (*C.RSA)(C.X_EVP_PKEY_get1_RSA(key.key))
if rsa == nil {
return nil, errors.New("failed getting rsa key")
}
@ -200,7 +174,7 @@ func (key *pKey) MarshalPKIXPublicKeyDER() (der_block []byte,
return nil, errors.New("failed to allocate memory BIO")
}
defer C.BIO_free(bio)
rsa := (*C.RSA)(C.EVP_PKEY_get1_RSA(key.key))
rsa := (*C.RSA)(C.X_EVP_PKEY_get1_RSA(key.key))
if rsa == nil {
return nil, errors.New("failed getting rsa key")
}
@ -230,18 +204,18 @@ func LoadPrivateKeyFromPEM(pem_block []byte) (PrivateKey, error) {
defer C.RSA_free(rsakey)
// convert to PKEY
key := C.EVP_PKEY_new()
key := C.X_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)
if C.X_EVP_PKEY_set1_RSA(key, (*C.struct_rsa_st)(rsakey)) != 1 {
C.X_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)
C.X_EVP_PKEY_free(p.key)
})
return p, nil
}
@ -267,18 +241,18 @@ func LoadPrivateKeyFromPEMWithPassword(pem_block []byte, password string) (
defer C.RSA_free(rsakey)
// convert to PKEY
key := C.EVP_PKEY_new()
key := C.X_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)
if C.X_EVP_PKEY_set1_RSA(key, (*C.struct_rsa_st)(rsakey)) != 1 {
C.X_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)
C.X_EVP_PKEY_free(p.key)
})
return p, nil
}
@ -302,18 +276,18 @@ func LoadPrivateKeyFromDER(der_block []byte) (PrivateKey, error) {
defer C.RSA_free(rsakey)
// convert to PKEY
key := C.EVP_PKEY_new()
key := C.X_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)
if C.X_EVP_PKEY_set1_RSA(key, (*C.struct_rsa_st)(rsakey)) != 1 {
C.X_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)
C.X_EVP_PKEY_free(p.key)
})
return p, nil
}
@ -344,18 +318,18 @@ func LoadPublicKeyFromPEM(pem_block []byte) (PublicKey, error) {
defer C.RSA_free(rsakey)
// convert to PKEY
key := C.EVP_PKEY_new()
key := C.X_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)
if C.X_EVP_PKEY_set1_RSA(key, (*C.struct_rsa_st)(rsakey)) != 1 {
C.X_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)
C.X_EVP_PKEY_free(p.key)
})
return p, nil
}
@ -379,18 +353,18 @@ func LoadPublicKeyFromDER(der_block []byte) (PublicKey, error) {
defer C.RSA_free(rsakey)
// convert to PKEY
key := C.EVP_PKEY_new()
key := C.X_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)
if C.X_EVP_PKEY_set1_RSA(key, (*C.struct_rsa_st)(rsakey)) != 1 {
C.X_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)
C.X_EVP_PKEY_free(p.key)
})
return p, nil
}
@ -406,17 +380,17 @@ func GenerateRSAKeyWithExponent(bits int, exponent int) (PrivateKey, error) {
if rsa == nil {
return nil, errors.New("failed to generate RSA key")
}
key := C.EVP_PKEY_new()
key := C.X_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)
if C.X_EVP_PKEY_assign_charp(key, C.EVP_PKEY_RSA, (*C.char)(unsafe.Pointer(rsa))) != 1 {
C.X_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)
C.X_EVP_PKEY_free(p.key)
})
return p, nil
}

View File

@ -1,162 +0,0 @@
// 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
import (
"errors"
"net"
"time"
)
const (
SSLRecordSize = 16 * 1024
)
type Conn struct{}
func Client(conn net.Conn, ctx *Ctx) (*Conn, error)
func Server(conn net.Conn, ctx *Ctx) (*Conn, error)
func (c *Conn) Handshake() error
func (c *Conn) PeerCertificate() (*Certificate, error)
func (c *Conn) Close() error
func (c *Conn) Read(b []byte) (n int, err error)
func (c *Conn) Write(b []byte) (written int, err error)
func (c *Conn) VerifyHostname(host string) error
func (c *Conn) LocalAddr() net.Addr
func (c *Conn) RemoteAddr() net.Addr
func (c *Conn) SetDeadline(t time.Time) error
func (c *Conn) SetReadDeadline(t time.Time) error
func (c *Conn) SetWriteDeadline(t time.Time) error
type Ctx struct{}
type SSLVersion int
const (
SSLv3 SSLVersion = 0x02
TLSv1 SSLVersion = 0x03
TLSv1_1 SSLVersion = 0x04
TLSv1_2 SSLVersion = 0x05
AnyVersion SSLVersion = 0x06
)
func NewCtxWithVersion(version SSLVersion) (*Ctx, error)
func NewCtx() (*Ctx, error)
func NewCtxFromFiles(cert_file string, key_file string) (*Ctx, error)
func (c *Ctx) UseCertificate(cert *Certificate) error
func (c *Ctx) UsePrivateKey(key PrivateKey) error
type CertificateStore struct{}
func (c *Ctx) GetCertificateStore() *CertificateStore
func (s *CertificateStore) AddCertificate(cert *Certificate) error
func (c *Ctx) LoadVerifyLocations(ca_file string, ca_path string) error
type Options int
const (
NoCompression Options = 0
NoSSLv2 Options = 0
NoSSLv3 Options = 0
NoTLSv1 Options = 0
CipherServerPreference Options = 0
NoSessionResumptionOrRenegotiation Options = 0
NoTicket Options = 0
)
func (c *Ctx) SetOptions(options Options) Options
type Modes int
const (
ReleaseBuffers Modes = 0
)
func (c *Ctx) SetMode(modes Modes) Modes
type VerifyOptions int
const (
VerifyNone VerifyOptions = 0
VerifyPeer VerifyOptions = 0
VerifyFailIfNoPeerCert VerifyOptions = 0
VerifyClientOnce VerifyOptions = 0
)
func (c *Ctx) SetVerify(options VerifyOptions)
func (c *Ctx) SetVerifyDepth(depth int)
func (c *Ctx) SetSessionId(session_id []byte) error
func (c *Ctx) SetCipherList(list string) error
type SessionCacheModes int
const (
SessionCacheOff SessionCacheModes = 0
SessionCacheClient SessionCacheModes = 0
SessionCacheServer SessionCacheModes = 0
SessionCacheBoth SessionCacheModes = 0
NoAutoClear SessionCacheModes = 0
NoInternalLookup SessionCacheModes = 0
NoInternalStore SessionCacheModes = 0
NoInternal SessionCacheModes = 0
)
func (c *Ctx) SetSessionCacheMode(modes SessionCacheModes) SessionCacheModes
var (
ValidationError = errors.New("Host validation error")
)
type CheckFlags int
const (
AlwaysCheckSubject CheckFlags = 0
NoWildcards CheckFlags = 0
)
func (c *Certificate) CheckHost(host string, flags CheckFlags) error
func (c *Certificate) CheckEmail(email string, flags CheckFlags) error
func (c *Certificate) CheckIP(ip net.IP, flags CheckFlags) error
func (c *Certificate) VerifyHostname(host string) error
type PublicKey interface {
MarshalPKIXPublicKeyPEM() (pem_block []byte, err error)
MarshalPKIXPublicKeyDER() (der_block []byte, err error)
evpPKey() struct{}
}
type PrivateKey interface {
PublicKey
MarshalPKCS1PrivateKeyPEM() (pem_block []byte, err error)
MarshalPKCS1PrivateKeyDER() (der_block []byte, err error)
}
func LoadPrivateKeyFromPEM(pem_block []byte) (PrivateKey, error)
type Certificate struct{}
func LoadCertificateFromPEM(pem_block []byte) (*Certificate, error)
func (c *Certificate) MarshalPEM() (pem_block []byte, err error)
func (c *Certificate) PublicKey() (PublicKey, error)

27
sha1.go
View File

@ -16,14 +16,7 @@
package openssl
/*
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "openssl/evp.h"
*/
// #include "shim.h"
import "C"
import (
@ -33,7 +26,7 @@ import (
)
type SHA1Hash struct {
ctx C.EVP_MD_CTX
ctx *C.EVP_MD_CTX
engine *Engine
}
@ -41,7 +34,10 @@ func NewSHA1Hash() (*SHA1Hash, error) { return NewSHA1HashWithEngine(nil) }
func NewSHA1HashWithEngine(e *Engine) (*SHA1Hash, error) {
hash := &SHA1Hash{engine: e}
C.EVP_MD_CTX_init(&hash.ctx)
hash.ctx = C.X_EVP_MD_CTX_new()
if hash.ctx == nil {
return nil, errors.New("openssl: sha1: unable to allocate ctx")
}
runtime.SetFinalizer(hash, func(hash *SHA1Hash) { hash.Close() })
if err := hash.Reset(); err != nil {
return nil, err
@ -50,7 +46,10 @@ func NewSHA1HashWithEngine(e *Engine) (*SHA1Hash, error) {
}
func (s *SHA1Hash) Close() {
C.EVP_MD_CTX_cleanup(&s.ctx)
if s.ctx != nil {
C.X_EVP_MD_CTX_free(s.ctx)
s.ctx = nil
}
}
func engineRef(e *Engine) *C.ENGINE {
@ -61,7 +60,7 @@ func engineRef(e *Engine) *C.ENGINE {
}
func (s *SHA1Hash) Reset() error {
if 1 != C.EVP_DigestInit_ex(&s.ctx, C.EVP_sha1(), engineRef(s.engine)) {
if 1 != C.X_EVP_DigestInit_ex(s.ctx, C.X_EVP_sha1(), engineRef(s.engine)) {
return errors.New("openssl: sha1: cannot init digest ctx")
}
return nil
@ -71,7 +70,7 @@ func (s *SHA1Hash) Write(p []byte) (n int, err error) {
if len(p) == 0 {
return 0, nil
}
if 1 != C.EVP_DigestUpdate(&s.ctx, unsafe.Pointer(&p[0]),
if 1 != C.X_EVP_DigestUpdate(s.ctx, unsafe.Pointer(&p[0]),
C.size_t(len(p))) {
return 0, errors.New("openssl: sha1: cannot update digest")
}
@ -79,7 +78,7 @@ func (s *SHA1Hash) Write(p []byte) (n int, err error) {
}
func (s *SHA1Hash) Sum() (result [20]byte, err error) {
if 1 != C.EVP_DigestFinal_ex(&s.ctx,
if 1 != C.X_EVP_DigestFinal_ex(s.ctx,
(*C.uchar)(unsafe.Pointer(&result[0])), nil) {
return result, errors.New("openssl: sha1: cannot finalize ctx")
}

View File

@ -16,14 +16,7 @@
package openssl
/*
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "openssl/evp.h"
*/
// #include "shim.h"
import "C"
import (
@ -33,7 +26,7 @@ import (
)
type SHA256Hash struct {
ctx C.EVP_MD_CTX
ctx *C.EVP_MD_CTX
engine *Engine
}
@ -41,7 +34,10 @@ func NewSHA256Hash() (*SHA256Hash, error) { return NewSHA256HashWithEngine(nil)
func NewSHA256HashWithEngine(e *Engine) (*SHA256Hash, error) {
hash := &SHA256Hash{engine: e}
C.EVP_MD_CTX_init(&hash.ctx)
hash.ctx = C.X_EVP_MD_CTX_new()
if hash.ctx == nil {
return nil, errors.New("openssl: sha256: unable to allocate ctx")
}
runtime.SetFinalizer(hash, func(hash *SHA256Hash) { hash.Close() })
if err := hash.Reset(); err != nil {
return nil, err
@ -50,11 +46,14 @@ func NewSHA256HashWithEngine(e *Engine) (*SHA256Hash, error) {
}
func (s *SHA256Hash) Close() {
C.EVP_MD_CTX_cleanup(&s.ctx)
if s.ctx != nil {
C.X_EVP_MD_CTX_free(s.ctx)
s.ctx = nil
}
}
func (s *SHA256Hash) Reset() error {
if 1 != C.EVP_DigestInit_ex(&s.ctx, C.EVP_sha256(), engineRef(s.engine)) {
if 1 != C.X_EVP_DigestInit_ex(s.ctx, C.X_EVP_sha256(), engineRef(s.engine)) {
return errors.New("openssl: sha256: cannot init digest ctx")
}
return nil
@ -64,7 +63,7 @@ func (s *SHA256Hash) Write(p []byte) (n int, err error) {
if len(p) == 0 {
return 0, nil
}
if 1 != C.EVP_DigestUpdate(&s.ctx, unsafe.Pointer(&p[0]),
if 1 != C.X_EVP_DigestUpdate(s.ctx, unsafe.Pointer(&p[0]),
C.size_t(len(p))) {
return 0, errors.New("openssl: sha256: cannot update digest")
}
@ -72,7 +71,7 @@ func (s *SHA256Hash) Write(p []byte) (n int, err error) {
}
func (s *SHA256Hash) Sum() (result [32]byte, err error) {
if 1 != C.EVP_DigestFinal_ex(&s.ctx,
if 1 != C.X_EVP_DigestFinal_ex(s.ctx,
(*C.uchar)(unsafe.Pointer(&result[0])), nil) {
return result, errors.New("openssl: sha256: cannot finalize ctx")
}

667
shim.c Normal file
View File

@ -0,0 +1,667 @@
/*
* 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.
*
*/
#ifndef SSL_MODE_RELEASE_BUFFERS
#define SSL_MODE_RELEASE_BUFFERS 0
#endif
#ifndef SSL_OP_NO_COMPRESSION
#define SSL_OP_NO_COMPRESSION 0
#endif
#include <string.h>
#include <openssl/conf.h>
#include <openssl/bio.h>
#include <openssl/crypto.h>
#include <openssl/engine.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/ssl.h>
#include "_cgo_export.h"
/*
* Functions defined in other .c files
*/
extern int go_init_locks();
extern void go_thread_locking_callback(int, int, const char*, int);
static int go_write_bio_puts(BIO *b, const char *str) {
return go_write_bio_write(b, (char*)str, (int)strlen(str));
}
/*
************************************************
* v1.1.X and later implementation
************************************************
*/
#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
void X_BIO_set_data(BIO* bio, void* data) {
BIO_set_data(bio, data);
}
void* X_BIO_get_data(BIO* bio) {
return BIO_get_data(bio);
}
EVP_MD_CTX* X_EVP_MD_CTX_new() {
return EVP_MD_CTX_new();
}
void X_EVP_MD_CTX_free(EVP_MD_CTX* ctx) {
EVP_MD_CTX_free(ctx);
}
static int x_bio_create(BIO *b) {
BIO_set_shutdown(b, 1);
BIO_set_init(b, 1);
BIO_set_data(b, NULL);
BIO_clear_flags(b, ~0);
return 1;
}
static int x_bio_free(BIO *b) {
return 1;
}
static BIO_METHOD *writeBioMethod;
static BIO_METHOD *readBioMethod;
BIO_METHOD* BIO_s_readBio() { return readBioMethod; }
BIO_METHOD* BIO_s_writeBio() { return writeBioMethod; }
int x_bio_init_methods() {
writeBioMethod = BIO_meth_new(BIO_TYPE_SOURCE_SINK, "Go Write BIO");
if (!writeBioMethod) {
return 1;
}
if (1 != BIO_meth_set_write(writeBioMethod,
(int (*)(BIO *, const char *, int))go_write_bio_write)) {
return 2;
}
if (1 != BIO_meth_set_puts(writeBioMethod, go_write_bio_puts)) {
return 3;
}
if (1 != BIO_meth_set_ctrl(writeBioMethod, go_write_bio_ctrl)) {
return 4;
}
if (1 != BIO_meth_set_create(writeBioMethod, x_bio_create)) {
return 5;
}
if (1 != BIO_meth_set_destroy(writeBioMethod, x_bio_free)) {
return 6;
}
readBioMethod = BIO_meth_new(BIO_TYPE_SOURCE_SINK, "Go Read BIO");
if (!readBioMethod) {
return 7;
}
if (1 != BIO_meth_set_read(readBioMethod, go_read_bio_read)) {
return 8;
}
if (1 != BIO_meth_set_ctrl(readBioMethod, go_read_bio_ctrl)) {
return 9;
}
if (1 != BIO_meth_set_create(readBioMethod, x_bio_create)) {
return 10;
}
if (1 != BIO_meth_set_destroy(readBioMethod, x_bio_free)) {
return 11;
}
return 0;
}
const EVP_MD *X_EVP_dss() {
return NULL;
}
const EVP_MD *X_EVP_dss1() {
return NULL;
}
const EVP_MD *X_EVP_sha() {
return NULL;
}
int X_EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx) {
return EVP_CIPHER_CTX_encrypting(ctx);
}
int X_X509_add_ref(X509* x509) {
return X509_up_ref(x509);
}
const ASN1_TIME *X_X509_get0_notBefore(const X509 *x) {
return X509_get0_notBefore(x);
}
const ASN1_TIME *X_X509_get0_notAfter(const X509 *x) {
return X509_get0_notAfter(x);
}
HMAC_CTX *X_HMAC_CTX_new(void) {
return HMAC_CTX_new();
}
void X_HMAC_CTX_free(HMAC_CTX *ctx) {
HMAC_CTX_free(ctx);
}
#endif
/*
************************************************
* v1.0.X implementation
************************************************
*/
#if OPENSSL_VERSION_NUMBER < 0x1010000fL
static int x_bio_create(BIO *b) {
b->shutdown = 1;
b->init = 1;
b->num = -1;
b->ptr = NULL;
b->flags = 0;
return 1;
}
static int x_bio_free(BIO *b) {
return 1;
}
static BIO_METHOD writeBioMethod = {
BIO_TYPE_SOURCE_SINK,
"Go Write BIO",
(int (*)(BIO *, const char *, int))go_write_bio_write,
NULL,
go_write_bio_puts,
NULL,
go_write_bio_ctrl,
x_bio_create,
x_bio_free,
NULL};
static BIO_METHOD* BIO_s_writeBio() { return &writeBioMethod; }
static BIO_METHOD readBioMethod = {
BIO_TYPE_SOURCE_SINK,
"Go Read BIO",
NULL,
go_read_bio_read,
NULL,
NULL,
go_read_bio_ctrl,
x_bio_create,
x_bio_free,
NULL};
static BIO_METHOD* BIO_s_readBio() { return &readBioMethod; }
int x_bio_init_methods() {
/* statically initialized above */
return 0;
}
void X_BIO_set_data(BIO* bio, void* data) {
bio->ptr = data;
}
void* X_BIO_get_data(BIO* bio) {
return bio->ptr;
}
EVP_MD_CTX* X_EVP_MD_CTX_new() {
return EVP_MD_CTX_create();
}
void X_EVP_MD_CTX_free(EVP_MD_CTX* ctx) {
EVP_MD_CTX_destroy(ctx);
}
int X_X509_add_ref(X509* x509) {
CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509);
return 1;
}
const ASN1_TIME *X_X509_get0_notBefore(const X509 *x) {
return x->cert_info->validity->notBefore;
}
const ASN1_TIME *X_X509_get0_notAfter(const X509 *x) {
return x->cert_info->validity->notAfter;
}
const EVP_MD *X_EVP_dss() {
return EVP_dss();
}
const EVP_MD *X_EVP_dss1() {
return EVP_dss1();
}
const EVP_MD *X_EVP_sha() {
return EVP_sha();
}
int X_EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx) {
return ctx->encrypt;
}
HMAC_CTX *X_HMAC_CTX_new(void) {
/* v1.1.0 uses a OPENSSL_zalloc to allocate the memory which does not exist
* in previous versions. malloc+memset to get the same behavior */
HMAC_CTX *ctx = (HMAC_CTX *)OPENSSL_malloc(sizeof(HMAC_CTX));
if (ctx) {
memset(ctx, 0, sizeof(HMAC_CTX));
HMAC_CTX_init(ctx);
}
return ctx;
}
void X_HMAC_CTX_free(HMAC_CTX *ctx) {
if (ctx) {
HMAC_CTX_cleanup(ctx);
OPENSSL_free(ctx);
}
}
#endif
/*
************************************************
* common implementation
************************************************
*/
int X_shim_init() {
int rc = 0;
OPENSSL_config(NULL);
ENGINE_load_builtin_engines();
SSL_load_error_strings();
SSL_library_init();
OpenSSL_add_all_algorithms();
//
// Set up OPENSSL thread safety callbacks. We only set the locking
// callback because the default id callback implementation is good
// enough for us.
rc = go_init_locks();
if (rc != 0) {
return rc;
}
CRYPTO_set_locking_callback(go_thread_locking_callback);
rc = x_bio_init_methods();
if (rc != 0) {
return rc;
}
return 0;
}
void X_OPENSSL_free(void *ref) {
OPENSSL_free(ref);
}
long X_SSL_set_options(SSL* ssl, long options) {
return SSL_set_options(ssl, options);
}
long X_SSL_get_options(SSL* ssl) {
return SSL_get_options(ssl);
}
long X_SSL_clear_options(SSL* ssl, long options) {
return SSL_clear_options(ssl, options);
}
long X_SSL_set_tlsext_host_name(SSL *ssl, const char *name) {
return SSL_set_tlsext_host_name(ssl, name);
}
const char * X_SSL_get_cipher_name(const SSL *ssl) {
return SSL_get_cipher_name(ssl);
}
int X_SSL_session_reused(SSL *ssl) {
return SSL_session_reused(ssl);
}
int X_SSL_new_index() {
return SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
}
int X_SSL_verify_cb(int ok, X509_STORE_CTX* store) {
SSL* ssl = (SSL *)X509_STORE_CTX_get_ex_data(store,
SSL_get_ex_data_X509_STORE_CTX_idx());
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 go_ssl_verify_cb_thunk(p, ok, store);
}
const SSL_METHOD *X_SSLv23_method() {
return SSLv23_method();
}
const SSL_METHOD *X_SSLv3_method() {
#ifndef OPENSSL_NO_SSL3_METHOD
return SSLv3_method();
#else
return NULL;
#endif
}
const SSL_METHOD *X_TLSv1_method() {
return TLSv1_method();
}
const SSL_METHOD *X_TLSv1_1_method() {
#if defined(TLS1_1_VERSION) && !defined(OPENSSL_SYSNAME_MACOSX)
return TLSv1_1_method();
#else
return NULL;
#endif
}
const SSL_METHOD *X_TLSv1_2_method() {
#if defined(TLS1_2_VERSION) && !defined(OPENSSL_SYSNAME_MACOSX)
return TLSv1_2_method();
#else
return NULL;
#endif
}
int X_SSL_CTX_new_index() {
return SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
}
long X_SSL_CTX_set_options(SSL_CTX* ctx, long options) {
return SSL_CTX_set_options(ctx, options);
}
long X_SSL_CTX_clear_options(SSL_CTX* ctx, long options) {
return SSL_CTX_clear_options(ctx, options);
}
long X_SSL_CTX_get_options(SSL_CTX* ctx) {
return SSL_CTX_get_options(ctx);
}
long X_SSL_CTX_set_mode(SSL_CTX* ctx, long modes) {
return SSL_CTX_set_mode(ctx, modes);
}
long X_SSL_CTX_get_mode(SSL_CTX* ctx) {
return SSL_CTX_get_mode(ctx);
}
long X_SSL_CTX_set_session_cache_mode(SSL_CTX* ctx, long modes) {
return SSL_CTX_set_session_cache_mode(ctx, modes);
}
long X_SSL_CTX_sess_set_cache_size(SSL_CTX* ctx, long t) {
return SSL_CTX_sess_set_cache_size(ctx, t);
}
long X_SSL_CTX_sess_get_cache_size(SSL_CTX* ctx) {
return SSL_CTX_sess_get_cache_size(ctx);
}
long X_SSL_CTX_set_timeout(SSL_CTX* ctx, long t) {
return SSL_CTX_set_timeout(ctx, t);
}
long X_SSL_CTX_get_timeout(SSL_CTX* ctx) {
return SSL_CTX_get_timeout(ctx);
}
long X_SSL_CTX_add_extra_chain_cert(SSL_CTX* ctx, X509 *cert) {
return SSL_CTX_add_extra_chain_cert(ctx, cert);
}
long X_SSL_CTX_set_tmp_ecdh(SSL_CTX* ctx, EC_KEY *key) {
return SSL_CTX_set_tmp_ecdh(ctx, key);
}
long X_SSL_CTX_set_tlsext_servername_callback(
SSL_CTX* ctx, int (*cb)(SSL *con, int *ad, void *args)) {
return SSL_CTX_set_tlsext_servername_callback(ctx, cb);
}
int X_SSL_CTX_verify_cb(int ok, X509_STORE_CTX* store) {
SSL* ssl = (SSL *)X509_STORE_CTX_get_ex_data(store,
SSL_get_ex_data_X509_STORE_CTX_idx());
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 go_ssl_ctx_verify_cb_thunk(p, ok, store);
}
long X_SSL_CTX_set_tmp_dh(SSL_CTX* ctx, DH *dh) {
return SSL_CTX_set_tmp_dh(ctx, dh);
}
long X_PEM_read_DHparams(SSL_CTX* ctx, DH *dh) {
return SSL_CTX_set_tmp_dh(ctx, dh);
}
int X_SSL_CTX_set_tlsext_ticket_key_cb(SSL_CTX *sslctx,
int (*cb)(SSL *s, unsigned char key_name[16],
unsigned char iv[EVP_MAX_IV_LENGTH],
EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int enc)) {
return SSL_CTX_set_tlsext_ticket_key_cb(sslctx, cb);
}
int X_SSL_CTX_ticket_key_cb(SSL *s, unsigned char key_name[16],
unsigned char iv[EVP_MAX_IV_LENGTH],
EVP_CIPHER_CTX *cctx, HMAC_CTX *hctx, int enc) {
SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(s);
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 go_ticket_key_cb_thunk(p, s, key_name, iv, cctx, hctx, enc);
}
int X_BIO_get_flags(BIO *b) {
return BIO_get_flags(b);
}
void X_BIO_set_flags(BIO *b, int flags) {
return BIO_set_flags(b, flags);
}
void X_BIO_clear_flags(BIO *b, int flags) {
BIO_clear_flags(b, flags);
}
int X_BIO_read(BIO *b, void *buf, int len) {
return BIO_read(b, buf, len);
}
int X_BIO_write(BIO *b, const void *buf, int len) {
return BIO_write(b, buf, len);
}
BIO *X_BIO_new_write_bio() {
return BIO_new(BIO_s_writeBio());
}
BIO *X_BIO_new_read_bio() {
return BIO_new(BIO_s_readBio());
}
const EVP_MD *X_EVP_get_digestbyname(const char *name) {
return EVP_get_digestbyname(name);
}
const EVP_MD *X_EVP_md_null() {
return EVP_md_null();
}
const EVP_MD *X_EVP_md5() {
return EVP_md5();
}
const EVP_MD *X_EVP_ripemd160() {
return EVP_ripemd160();
}
const EVP_MD *X_EVP_sha224() {
return EVP_sha224();
}
const EVP_MD *X_EVP_sha1() {
return EVP_sha1();
}
const EVP_MD *X_EVP_sha256() {
return EVP_sha256();
}
const EVP_MD *X_EVP_sha384() {
return EVP_sha384();
}
const EVP_MD *X_EVP_sha512() {
return EVP_sha512();
}
int X_EVP_MD_size(const EVP_MD *md) {
return EVP_MD_size(md);
}
int X_EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) {
return EVP_DigestInit_ex(ctx, type, impl);
}
int X_EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt) {
return EVP_DigestUpdate(ctx, d, cnt);
}
int X_EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s) {
return EVP_DigestFinal_ex(ctx, md, s);
}
int X_EVP_SignInit(EVP_MD_CTX *ctx, const EVP_MD *type) {
return EVP_SignInit(ctx, type);
}
int X_EVP_SignUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt) {
return EVP_SignUpdate(ctx, d, cnt);
}
EVP_PKEY *X_EVP_PKEY_new(void) {
return EVP_PKEY_new();
}
void X_EVP_PKEY_free(EVP_PKEY *pkey) {
EVP_PKEY_free(pkey);
}
int X_EVP_PKEY_size(EVP_PKEY *pkey) {
return EVP_PKEY_size(pkey);
}
struct rsa_st *X_EVP_PKEY_get1_RSA(EVP_PKEY *pkey) {
return EVP_PKEY_get1_RSA(pkey);
}
int X_EVP_PKEY_set1_RSA(EVP_PKEY *pkey, struct rsa_st *key) {
return EVP_PKEY_set1_RSA(pkey, key);
}
int X_EVP_PKEY_assign_charp(EVP_PKEY *pkey, int type, char *key) {
return EVP_PKEY_assign(pkey, type, key);
}
int X_EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s, EVP_PKEY *pkey) {
return EVP_SignFinal(ctx, md, s, pkey);
}
int X_EVP_VerifyInit(EVP_MD_CTX *ctx, const EVP_MD *type) {
return EVP_VerifyInit(ctx, type);
}
int X_EVP_VerifyUpdate(EVP_MD_CTX *ctx, const void *d,
unsigned int cnt) {
return EVP_VerifyUpdate(ctx, d, cnt);
}
int X_EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf, unsigned int siglen, EVP_PKEY *pkey) {
return EVP_VerifyFinal(ctx, sigbuf, siglen, pkey);
}
int X_EVP_CIPHER_block_size(EVP_CIPHER *c) {
return EVP_CIPHER_block_size(c);
}
int X_EVP_CIPHER_key_length(EVP_CIPHER *c) {
return EVP_CIPHER_key_length(c);
}
int X_EVP_CIPHER_iv_length(EVP_CIPHER *c) {
return EVP_CIPHER_iv_length(c);
}
int X_EVP_CIPHER_nid(EVP_CIPHER *c) {
return EVP_CIPHER_nid(c);
}
int X_EVP_CIPHER_CTX_block_size(EVP_CIPHER_CTX *ctx) {
return EVP_CIPHER_CTX_block_size(ctx);
}
int X_EVP_CIPHER_CTX_key_length(EVP_CIPHER_CTX *ctx) {
return EVP_CIPHER_CTX_key_length(ctx);
}
int X_EVP_CIPHER_CTX_iv_length(EVP_CIPHER_CTX *ctx) {
return EVP_CIPHER_CTX_iv_length(ctx);
}
const EVP_CIPHER *X_EVP_CIPHER_CTX_cipher(EVP_CIPHER_CTX *ctx) {
return EVP_CIPHER_CTX_cipher(ctx);
}
size_t X_HMAC_size(const HMAC_CTX *e) {
return HMAC_size(e);
}
int X_HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md, ENGINE *impl) {
return HMAC_Init_ex(ctx, key, len, md, impl);
}
int X_HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len) {
return HMAC_Update(ctx, data, len);
}
int X_HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len) {
return HMAC_Final(ctx, md, len);
}
int X_sk_X509_num(STACK_OF(X509) *sk) {
return sk_X509_num(sk);
}
X509 *X_sk_X509_value(STACK_OF(X509)* sk, int i) {
return sk_X509_value(sk, i);
}

149
shim.h Normal file
View File

@ -0,0 +1,149 @@
/*
* 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 <stdlib.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/crypto.h>
#include <openssl/dh.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/x509v3.h>
/* shim methods */
extern int X_shim_init();
/* Library methods */
extern void X_OPENSSL_free(void *ref);
/* SSL methods */
extern long X_SSL_set_options(SSL* ssl, long options);
extern long X_SSL_get_options(SSL* ssl);
extern long X_SSL_clear_options(SSL* ssl, long options);
extern long X_SSL_set_tlsext_host_name(SSL *ssl, const char *name);
extern const char * X_SSL_get_cipher_name(const SSL *ssl);
extern int X_SSL_session_reused(SSL *ssl);
extern int X_SSL_new_index();
extern const SSL_METHOD *X_SSLv23_method();
extern const SSL_METHOD *X_SSLv3_method();
extern const SSL_METHOD *X_TLSv1_method();
extern const SSL_METHOD *X_TLSv1_1_method();
extern const SSL_METHOD *X_TLSv1_2_method();
#if defined SSL_CTRL_SET_TLSEXT_HOSTNAME
extern int sni_cb(SSL *ssl_conn, int *ad, void *arg);
#endif
extern int X_SSL_verify_cb(int ok, X509_STORE_CTX* store);
/* SSL_CTX methods */
extern int X_SSL_CTX_new_index();
extern long X_SSL_CTX_set_options(SSL_CTX* ctx, long options);
extern long X_SSL_CTX_clear_options(SSL_CTX* ctx, long options);
extern long X_SSL_CTX_get_options(SSL_CTX* ctx);
extern long X_SSL_CTX_set_mode(SSL_CTX* ctx, long modes);
extern long X_SSL_CTX_get_mode(SSL_CTX* ctx);
extern long X_SSL_CTX_set_session_cache_mode(SSL_CTX* ctx, long modes);
extern long X_SSL_CTX_sess_set_cache_size(SSL_CTX* ctx, long t);
extern long X_SSL_CTX_sess_get_cache_size(SSL_CTX* ctx);
extern long X_SSL_CTX_set_timeout(SSL_CTX* ctx, long t);
extern long X_SSL_CTX_get_timeout(SSL_CTX* ctx);
extern long X_SSL_CTX_add_extra_chain_cert(SSL_CTX* ctx, X509 *cert);
extern long X_SSL_CTX_set_tmp_ecdh(SSL_CTX* ctx, EC_KEY *key);
extern long X_SSL_CTX_set_tlsext_servername_callback(SSL_CTX* ctx, int (*cb)(SSL *con, int *ad, void *args));
extern int X_SSL_CTX_verify_cb(int ok, X509_STORE_CTX* store);
extern long X_SSL_CTX_set_tmp_dh(SSL_CTX* ctx, DH *dh);
extern long X_PEM_read_DHparams(SSL_CTX* ctx, DH *dh);
extern int X_SSL_CTX_set_tlsext_ticket_key_cb(SSL_CTX *sslctx,
int (*cb)(SSL *s, unsigned char key_name[16],
unsigned char iv[EVP_MAX_IV_LENGTH],
EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int enc));
extern int X_SSL_CTX_ticket_key_cb(SSL *s, unsigned char key_name[16],
unsigned char iv[EVP_MAX_IV_LENGTH],
EVP_CIPHER_CTX *cctx, HMAC_CTX *hctx, int enc);
/* BIO methods */
extern int X_BIO_get_flags(BIO *b);
extern void X_BIO_set_flags(BIO *bio, int flags);
extern void X_BIO_clear_flags(BIO *bio, int flags);
extern void X_BIO_set_data(BIO *bio, void* data);
extern void *X_BIO_get_data(BIO *bio);
extern int X_BIO_read(BIO *b, void *buf, int len);
extern int X_BIO_write(BIO *b, const void *buf, int len);
extern BIO *X_BIO_new_write_bio();
extern BIO *X_BIO_new_read_bio();
/* EVP methods */
extern const EVP_MD *X_EVP_get_digestbyname(const char *name);
extern EVP_MD_CTX *X_EVP_MD_CTX_new();
extern void X_EVP_MD_CTX_free(EVP_MD_CTX *ctx);
extern const EVP_MD *X_EVP_md_null();
extern const EVP_MD *X_EVP_md5();
extern const EVP_MD *X_EVP_sha();
extern const EVP_MD *X_EVP_sha1();
extern const EVP_MD *X_EVP_dss();
extern const EVP_MD *X_EVP_dss1();
extern const EVP_MD *X_EVP_ripemd160();
extern const EVP_MD *X_EVP_sha224();
extern const EVP_MD *X_EVP_sha256();
extern const EVP_MD *X_EVP_sha384();
extern const EVP_MD *X_EVP_sha512();
extern int X_EVP_MD_size(const EVP_MD *md);
extern int X_EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl);
extern int X_EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt);
extern int X_EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s);
extern int X_EVP_SignInit(EVP_MD_CTX *ctx, const EVP_MD *type);
extern int X_EVP_SignUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt);
extern EVP_PKEY *X_EVP_PKEY_new(void);
extern void X_EVP_PKEY_free(EVP_PKEY *pkey);
extern int X_EVP_PKEY_size(EVP_PKEY *pkey);
extern struct rsa_st *X_EVP_PKEY_get1_RSA(EVP_PKEY *pkey);
extern int X_EVP_PKEY_set1_RSA(EVP_PKEY *pkey, struct rsa_st *key);
extern int X_EVP_PKEY_assign_charp(EVP_PKEY *pkey, int type, char *key);
extern int X_EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s, EVP_PKEY *pkey);
extern int X_EVP_VerifyInit(EVP_MD_CTX *ctx, const EVP_MD *type);
extern int X_EVP_VerifyUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt);
extern int X_EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf, unsigned int siglen, EVP_PKEY *pkey);
extern int X_EVP_CIPHER_block_size(EVP_CIPHER *c);
extern int X_EVP_CIPHER_key_length(EVP_CIPHER *c);
extern int X_EVP_CIPHER_iv_length(EVP_CIPHER *c);
extern int X_EVP_CIPHER_nid(EVP_CIPHER *c);
extern int X_EVP_CIPHER_CTX_block_size(EVP_CIPHER_CTX *ctx);
extern int X_EVP_CIPHER_CTX_key_length(EVP_CIPHER_CTX *ctx);
extern int X_EVP_CIPHER_CTX_iv_length(EVP_CIPHER_CTX *ctx);
extern const EVP_CIPHER *X_EVP_CIPHER_CTX_cipher(EVP_CIPHER_CTX *ctx);
extern int X_EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx);
/* HMAC methods */
extern size_t X_HMAC_size(const HMAC_CTX *e);
extern HMAC_CTX *X_HMAC_CTX_new(void);
extern void X_HMAC_CTX_free(HMAC_CTX *ctx);
extern int X_HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md, ENGINE *impl);
extern int X_HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len);
extern int X_HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len);
/* X509 methods */
extern int X_X509_add_ref(X509* x509);
extern const ASN1_TIME *X_X509_get0_notBefore(const X509 *x);
extern const ASN1_TIME *X_X509_get0_notAfter(const X509 *x);
extern int X_sk_X509_num(STACK_OF(X509) *sk);
extern X509 *X_sk_X509_value(STACK_OF(X509)* sk, int i);

35
ssl.go
View File

@ -16,26 +16,7 @@
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);
*/
// #include "shim.h"
import "C"
import (
@ -53,7 +34,7 @@ const (
)
var (
ssl_idx = C.SSL_get_ex_new_index(0, nil, nil, nil, nil)
ssl_idx = C.X_SSL_new_index()
)
//export get_ssl_idx
@ -66,8 +47,8 @@ type SSL struct {
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 {
//export go_ssl_verify_cb_thunk
func go_ssl_verify_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)
@ -96,19 +77,19 @@ func (s *SSL) GetServername() string {
// 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))
return Options(C.X_SSL_get_options(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)))
return Options(C.X_SSL_set_options(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)))
return Options(C.X_SSL_clear_options(s.ssl, C.long(options)))
}
// SetVerify controls peer verification settings. See
@ -116,7 +97,7 @@ func (s *SSL) ClearOptions(options Options) Options {
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))
C.SSL_set_verify(s.ssl, C.int(options), (*[0]byte)(C.X_SSL_verify_cb))
} else {
C.SSL_set_verify(s.ssl, C.int(options), nil)
}

View File

@ -1,27 +0,0 @@
// 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.
#include <openssl/ssl.h>
#include <openssl/evp.h>
#include "_cgo_export.h"
int ticket_key_cb(SSL *s, unsigned char key_name[16],
unsigned char iv[EVP_MAX_IV_LENGTH],
EVP_CIPHER_CTX *cctx, HMAC_CTX *hctx, int enc) {
SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(s);
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 ticket_key_cb_thunk(p, s, key_name, iv, cctx, hctx, enc);
}

View File

@ -16,22 +16,7 @@
package openssl
/*
#include <openssl/ssl.h>
#include <openssl/evp.h>
static int SSL_CTX_set_tlsext_ticket_key_cb_not_a_macro(SSL_CTX *sslctx,
int (*cb)(SSL *s, unsigned char key_name[16],
unsigned char iv[EVP_MAX_IV_LENGTH],
EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int enc)) {
return SSL_CTX_set_tlsext_ticket_key_cb(sslctx, cb);
}
extern int ticket_key_cb(SSL *s, unsigned char key_name[16],
unsigned char iv[EVP_MAX_IV_LENGTH],
EVP_CIPHER_CTX *cctx, HMAC_CTX *hctx, int enc);
*/
// #include "shim.h"
import "C"
import (
@ -131,8 +116,8 @@ const (
ticket_req_lookupSession = 0
)
//export ticket_key_cb_thunk
func ticket_key_cb_thunk(p unsafe.Pointer, s *C.SSL, key_name *C.uchar,
//export go_ticket_key_cb_thunk
func go_ticket_key_cb_thunk(p unsafe.Pointer, s *C.SSL, key_name *C.uchar,
iv *C.uchar, cctx *C.EVP_CIPHER_CTX, hctx *C.HMAC_CTX, enc C.int) C.int {
// no panic's allowed. it's super hard to guarantee any state at this point
@ -231,9 +216,9 @@ func (c *Ctx) SetTicketStore(store *TicketStore) {
c.ticket_store = store
if store == nil {
C.SSL_CTX_set_tlsext_ticket_key_cb_not_a_macro(c.ctx, nil)
C.X_SSL_CTX_set_tlsext_ticket_key_cb(c.ctx, nil)
} else {
C.SSL_CTX_set_tlsext_ticket_key_cb_not_a_macro(c.ctx,
(*[0]byte)(C.ticket_key_cb))
C.X_SSL_CTX_set_tlsext_ticket_key_cb(c.ctx,
(*[0]byte)(C.X_SSL_CTX_ticket_key_cb))
}
}

View File

@ -1,31 +0,0 @@
// 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"
int verify_cb(int ok, X509_STORE_CTX* store) {
SSL* ssl = (SSL *)X509_STORE_CTX_get_app_data(store);
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);
}