security: Fix up use of OpenSSL

The switch to Go 1.6 means that there is no advantage to using OpenSSL's
crypto library (libcrypto) for ECDSA signing and verification on amd64.
However, on other architectures (such as ARM-based RaspberryPis and
Androids or Intel Edisons (386)) using libcrypto may still yield a
performance benefit over the implementation in the standard Go library
(which lacks optimized assembly for these architectures).

This change fixes up use of OpenSSL's libcrypto in this post 1.6 world.

(1) Simplified build tags: By default use the Go standard library.
    When the 'openssl' tag is specified, use that.

(2) Use cgo in a manner compatible with the stricter rules on
    pointer passing introduced in Go 1.6 (see
    https://golang.org/doc/go1.6#cgo).

    Specifically d2i_EC_PUBKEY and d2i_ECPrivateKey take
    an argument of type (char**), causing Go 1.6 to complain
    with a panic:
    "panic: runtime error: cgo argument has Go pointer to Go pointer"
    if that argument was backed by memory allocated by the Go runtime.

    However, the only reason the d2i_* functions take a
    pointer-to-a-pointer is to increment the input to
    the address following the parsed data (see
    https://www.openssl.org/docs/manmaster/crypto/d2i_X509.html),
    not to allocate memory and assign to that pointer.

    Thus, in this change, the wrapper openssl_d2i_* functions in
    openssl.c have been modified to trick the Go runtime into avoiding
    that check. This will cause subtle bugs if I misunderstood the
    contract the d2i_* functions have.

Change-Id: I62a3ebecee7c2afdc3f70f961f26a5db488cff6d
diff --git a/security/ecdsa_go.go b/security/ecdsa_go.go
index bff1875..606f9e9 100644
--- a/security/ecdsa_go.go
+++ b/security/ecdsa_go.go
@@ -2,10 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build go1.6 !cgo noopenssl !linux,!openssl android !amd64,!openssl
-
-// See comments in ecdsa_openssl.go for an explanation of the choice of
-// build tags.
+// +build !openssl
 
 package security
 
diff --git a/security/ecdsa_openssl.go b/security/ecdsa_openssl.go
index e9573d7..9c10116 100644
--- a/security/ecdsa_openssl.go
+++ b/security/ecdsa_openssl.go
@@ -2,31 +2,12 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !go1.6,!android,linux,amd64,cgo,!noopenssl openssl,cgo
+// +build openssl
 
-// The purpose of this file is to improve performance, as demonstrated by
-// benchmarks when linked against openssl-1.0.1f (with further improvements in
-// openssl-1.0.2, at the time this comment was written).
-//   go test -bench ECDSA v.io/v23/security
-//
-// With Go 1.6, the Go standard library will have performance on-par with
-// OpenSSL for amd64 (see https://go-review.googlesource.com/#/c/8968/).
-// Prior to that however, using OpenSSL (via cgo) provides a significant
-// performance improvement.
-//
-// By default (without an explicit build tag), this is disabled for darwin
-// since OpenSSL has been marked deprecated on OS X since version 10.7.  The
-// last openssl release on OS X was version 0.9.8 and compiling this file will
-// show these deprecation warnings.  Those sensitive to performance are
-// encouraged to move to Go 1.6.
-//
-// Currently, this file is disabled for linux/arm as a temporary hack.  In
-// practice, linux/arm binaries are often cross-compiled on a linux/amd64 host.
-// The author of this comment hadn't changed the vanadium devtools to download
-// and build a cross-compiled OpenSSL library at the time this comment was
-// written.
-//
-// TODO(ashankar): Figure out how to remove the "amd64" tag hack.
+// OpenSSL's libcrypto may have faster implementations of ECDSA signing and
+// verification on some architectures (not amd64 after Go 1.6 which includes
+// https://go-review.googlesource.com/#/c/8968/). This file enables use
+// of libcrypto's implementation of ECDSA operations in those situations.
 
 package security
 
@@ -40,8 +21,8 @@
 // #include <openssl/x509.h>
 //
 // void openssl_init_locks();
-// EC_KEY* openssl_d2i_EC_PUBKEY(const unsigned char** data, long len, unsigned long* e);
-// EC_KEY* openssl_d2i_ECPrivateKey(const unsigned char** data, long len, unsigned long* e);
+// EC_KEY* openssl_d2i_EC_PUBKEY(const unsigned char* data, long len, unsigned long* e);
+// EC_KEY* openssl_d2i_ECPrivateKey(const unsigned char* data, long len, unsigned long* e);
 // ECDSA_SIG* openssl_ECDSA_do_sign(const unsigned char* data, int len, EC_KEY* key, unsigned long *e);
 import "C"
 
@@ -153,8 +134,7 @@
 		return nil, err
 	}
 	var errno C.ulong
-	in := uchar(der)
-	k := C.openssl_d2i_ECPrivateKey(&in, C.long(len(der)), &errno)
+	k := C.openssl_d2i_ECPrivateKey(uchar(der), C.long(len(der)), &errno)
 	if k == nil {
 		return nil, opensslMakeError(errno)
 	}
@@ -211,8 +191,7 @@
 
 func unmarshalPublicKeyImpl(der []byte) (PublicKey, error) {
 	var errno C.ulong
-	in := uchar(der)
-	k := C.openssl_d2i_EC_PUBKEY(&in, C.long(len(der)), &errno)
+	k := C.openssl_d2i_EC_PUBKEY(uchar(der), C.long(len(der)), &errno)
 	if k == nil {
 		return nil, opensslMakeError(errno)
 	}
diff --git a/security/ecdsa_openssl_test.go b/security/ecdsa_openssl_test.go
index cba249b..190399a 100644
--- a/security/ecdsa_openssl_test.go
+++ b/security/ecdsa_openssl_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !go1.6,!android,linux,amd64,cgo,!noopenssl openssl,cgo
+// +build openssl
 
 package security
 
diff --git a/security/openssl.c b/security/openssl.c
index 7f29e07..2d607d5 100644
--- a/security/openssl.c
+++ b/security/openssl.c
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !go1.6,!android,linux,amd64,cgo,!noopenssl openssl,cgo
+// +build openssl
 
 #include <openssl/crypto.h>
 #include <openssl/ec.h>
@@ -23,8 +23,8 @@
 // as the call to d2i_ECPrivateKey. If the two were called from Go, the goroutine
 // might be pre-empted and rescheduled on another thread leading to an
 // inconsistent error.
-EC_KEY* openssl_d2i_ECPrivateKey(const unsigned char** data, long len, unsigned long* e) {
-	EC_KEY* k = d2i_ECPrivateKey(NULL, data, len);
+EC_KEY* openssl_d2i_ECPrivateKey(const unsigned char* data, long len, unsigned long* e) {
+	EC_KEY* k = d2i_ECPrivateKey(NULL, &data, len);
 	if (k != NULL) {
 		*e = 0;
 		return k;
@@ -38,8 +38,8 @@
 // as the call to d2i_EC_PUBKEY. If the two were called from Go, the goroutine
 // might be pre-empted and rescheduled on another thread leading to an
 // inconsistent error.
-EC_KEY* openssl_d2i_EC_PUBKEY(const unsigned char** data, long len, unsigned long* e) {
-	EC_KEY* k = d2i_EC_PUBKEY(NULL, data, len);
+EC_KEY* openssl_d2i_EC_PUBKEY(const unsigned char* data, long len, unsigned long* e) {
+	EC_KEY* k = d2i_EC_PUBKEY(NULL, &data, len);
 	if (k != NULL) {
 		*e = 0;
 		return k;