Skip to content

Support Windows #48

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,16 @@ jobs:
run: go test -gcflags=all=-d=checkptr -count 10 -v ./...
env:
GO_OPENSSL_VERSION_OVERRIDE: ${{ matrix.openssl-version }}
wintest:
runs-on: windows-2022
steps:
- name: Install Go
uses: actions/setup-go@v3
with:
go-version: 1.19.x
- name: Checkout code
uses: actions/checkout@v3
- name: Run Test
run: go test -gcflags=all=-d=checkptr -v ./...
env:
GO_OPENSSL_VERSION_OVERRIDE: -1_1-x64
3 changes: 0 additions & 3 deletions openssl/aes.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
//go:build linux && !android
// +build linux,!android

package openssl

// #include "goopenssl.h"
Expand Down
22 changes: 11 additions & 11 deletions openssl/big.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package openssl
// This file does not have build constraints to
// facilitate using BigInt in Go crypto.
// Go crypto references BigInt unconditionally,
// even if it is not finally used.
// A BigInt is the raw words from a BigInt.
// This definition allows us to avoid importing math/big.
// Conversion between BigInt and *big.Int is in openssl/bbig.
type BigInt []uint
package openssl

// This file does not have build constraints to
// facilitate using BigInt in Go crypto.
// Go crypto references BigInt unconditionally,
// even if it is not finally used.

// A BigInt is the raw words from a BigInt.
// This definition allows us to avoid importing math/big.
// Conversion between BigInt and *big.Int is in openssl/bbig.
type BigInt []uint
3 changes: 0 additions & 3 deletions openssl/ecdh.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
//go:build linux && !android
// +build linux,!android

package openssl

// #include "goopenssl.h"
Expand Down
3 changes: 0 additions & 3 deletions openssl/ecdh_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
//go:build linux && !android
// +build linux,!android

package openssl_test

import (
Expand Down
3 changes: 0 additions & 3 deletions openssl/ecdsa.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
//go:build linux && !android
// +build linux,!android

package openssl

// #include "goopenssl.h"
Expand Down
3 changes: 0 additions & 3 deletions openssl/ecdsa_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
//go:build linux && !android
// +build linux,!android

package openssl_test

import (
Expand Down
3 changes: 0 additions & 3 deletions openssl/evp.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
//go:build linux && !android
// +build linux,!android

package openssl

// #include "goopenssl.h"
Expand Down
28 changes: 19 additions & 9 deletions openssl/goopenssl.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
//go:build linux && !android
// +build linux,!android

#include "goopenssl.h"

#include <dlfcn.h> // dlsym
#ifdef _WIN32
#include <windows.h>
#else
#include <dlfcn.h>
#endif
#include <stdio.h> // fprintf

// Approach taken from .Net System.Security.Cryptography.Native
Expand All @@ -27,6 +28,15 @@ FOR_ALL_OPENSSL_FUNCTIONS
#undef DEFINEFUNC_RENAMED_1_1
#undef DEFINEFUNC_RENAMED_3_0

static void *
go_openssl_dlsym(void* handle, const char* name)
{
#ifdef _WIN32
return GetProcAddress(handle, name);
#else
return dlsym(handle, name);
#endif
}

// Load all the functions stored in FOR_ALL_OPENSSL_FUNCTIONS
// and assign them to their corresponding function pointer
Expand All @@ -35,7 +45,7 @@ void
go_openssl_load_functions(void* handle, int major, int minor)
{
#define DEFINEFUNC_INTERNAL(name, func) \
_g_##name = dlsym(handle, func); \
_g_##name = go_openssl_dlsym(handle, func); \
if (_g_##name == NULL) { \
fprintf(stderr, "Cannot get required symbol " #func " from libcrypto version %d.%d\n", major, minor); \
abort(); \
Expand Down Expand Up @@ -97,12 +107,12 @@ version_num(void* handle)
{
unsigned long (*fn)(void);
// OPENSSL_version_num is defined in OpenSSL 1.1.0 and 1.1.1.
fn = (unsigned long (*)(void))dlsym(handle, "OpenSSL_version_num");
fn = (unsigned long (*)(void))go_openssl_dlsym(handle, "OpenSSL_version_num");
if (fn != NULL)
return fn();

// SSLeay is defined in OpenSSL 1.0.2.
fn = (unsigned long (*)(void))dlsym(handle, "SSLeay");
fn = (unsigned long (*)(void))go_openssl_dlsym(handle, "SSLeay");
if (fn != NULL)
return fn();

Expand All @@ -114,7 +124,7 @@ go_openssl_version_major(void* handle)
{
unsigned int (*fn)(void);
// OPENSSL_version_major is supported since OpenSSL 3.
fn = (unsigned int (*)(void))dlsym(handle, "OPENSSL_version_major");
fn = (unsigned int (*)(void))go_openssl_dlsym(handle, "OPENSSL_version_major");
if (fn != NULL)
return (int)fn();

Expand All @@ -131,7 +141,7 @@ go_openssl_version_minor(void* handle)
{
unsigned int (*fn)(void);
// OPENSSL_version_minor is supported since OpenSSL 3.
fn = (unsigned int (*)(void))dlsym(handle, "OPENSSL_version_minor");
fn = (unsigned int (*)(void))go_openssl_dlsym(handle, "OPENSSL_version_minor");
if (fn != NULL)
return (int)fn();

Expand Down
3 changes: 0 additions & 3 deletions openssl/hmac.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
//go:build linux && !android
// +build linux,!android

package openssl

// #include "goopenssl.h"
Expand Down
3 changes: 0 additions & 3 deletions openssl/hmac_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
//go:build linux && !android
// +build linux,!android

package openssl

import (
Expand Down
26 changes: 8 additions & 18 deletions openssl/init.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
//go:build linux && !android
// +build linux,!android
//go:build windows || (linux && !android)
// +build windows linux,!android

package openssl

// #include "goopenssl.h"
// #include <dlfcn.h>
import "C"
import (
"errors"
"runtime"
"unsafe"
)

Expand Down Expand Up @@ -74,27 +74,17 @@ func opensslInit(version string) (major int, minor int, err error) {
return major, minor, nil
}

func dlopen(version string) unsafe.Pointer {
cv := C.CString("libcrypto.so." + version)
defer C.free(unsafe.Pointer(cv))
return C.dlopen(cv, C.RTLD_LAZY|C.RTLD_LOCAL)
}

func loadLibrary(version string) (unsafe.Pointer, error) {
if version != "" {
if version != "" || runtime.GOARCH == "windows" {
// If version is specified try to load it or error out.
handle := dlopen(version)
if handle == nil {
errstr := C.GoString(C.dlerror())
return nil, errors.New("openssl: can't load libcrypto.so." + version + ": " + errstr)
}
return handle, nil
// Windows does not support the list of well known versions.
return dlopen(version)
}
// If the version is not specified, try loading from the list
// of well known versions.
for _, v := range knownVersions {
handle := dlopen(v)
if handle == nil {
handle, err := dlopen(v)
if err != nil {
continue
}
return handle, nil
Expand Down
4 changes: 0 additions & 4 deletions openssl/openssl.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
//go:build linux && !android
// +build linux,!android

// Package openssl provides access to OpenSSL cryptographic functions.
package openssl

// #include "goopenssl.h"
// #cgo LDFLAGS: -ldl
import "C"
import (
"encoding/binary"
Expand Down
21 changes: 21 additions & 0 deletions openssl/openssl_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package openssl

// #include <stdlib.h> // free
// #include <dlfcn.h>
// #cgo LDFLAGS: -ldl
import "C"
import (
"errors"
"unsafe"
)

func dlopen(version string) (unsafe.Pointer, error) {
cv := C.CString("libcrypto.so." + version)
defer C.free(unsafe.Pointer(cv))
h := C.dlopen(cv, C.RTLD_LAZY|C.RTLD_LOCAL)
if h == nil {
errstr := C.GoString(C.dlerror())
return nil, errors.New("openssl: can't load libcrypto.so." + version + ": " + errstr)
}
return h, nil
}
3 changes: 0 additions & 3 deletions openssl/openssl_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
//go:build linux && !android
// +build linux,!android

package openssl_test

import (
Expand Down
23 changes: 23 additions & 0 deletions openssl/openssl_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package openssl

// #include <windows.h>
import "C"
import (
"runtime"
"syscall"
"unsafe"
)

func dlopen(version string) (unsafe.Pointer, error) {
name, err := syscall.UTF16PtrFromString("libcrypto" + version + ".dll")
if err != nil {
return nil, err
}
h := C.LoadLibraryExW((*C.ushort)(unsafe.Pointer(name)), nil, C.LOAD_LIBRARY_SEARCH_SYSTEM32)
runtime.KeepAlive(name)
if h == nil {
code := C.GetLastError()
return nil, syscall.Errno(code)
}
return unsafe.Pointer(h), nil
}
3 changes: 0 additions & 3 deletions openssl/params.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
//go:build linux && !android
// +build linux,!android

package openssl

// #include "goopenssl.h"
Expand Down
3 changes: 0 additions & 3 deletions openssl/rand.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
//go:build linux && !android
// +build linux,!android

package openssl

// #include "goopenssl.h"
Expand Down
3 changes: 0 additions & 3 deletions openssl/rand_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
//go:build linux && !android
// +build linux,!android

package openssl_test

import (
Expand Down
3 changes: 0 additions & 3 deletions openssl/rsa.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
//go:build linux && !android
// +build linux,!android

package openssl

// #include "goopenssl.h"
Expand Down
6 changes: 0 additions & 6 deletions openssl/rsa_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

//go:build linux && !android
// +build linux,!android

package openssl_test

import (
Expand Down
3 changes: 0 additions & 3 deletions openssl/sha.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
//go:build linux && !android
// +build linux,!android

package openssl

// #include "goopenssl.h"
Expand Down
3 changes: 0 additions & 3 deletions openssl/sha_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
//go:build linux && !android
// +build linux,!android

package openssl_test

import (
Expand Down
File renamed without changes.
8 changes: 8 additions & 0 deletions openssl/thread_setup_windows.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//go:build windows
// +build windows

int go_openssl_thread_setup(void)
{
// OpenSSL 1.0.2 not supported on Windows.
return 0;
}