From 9bd70da361ad3f1abf9b99d9f3ae7be2d16e2528 Mon Sep 17 00:00:00 2001 From: Oleg Jukovec Date: Thu, 14 Apr 2022 16:28:08 +0300 Subject: [PATCH 1/3] Fix build with OpenSSL 3.0 - FIPS_mode_set() does not exist in OpenSSL 3.0 [1] - X509_check_* functions declarated in openssl/x509v3.h instead of openssl/x509.h [2] - X509_chack_* functions have const char arg inserad of const unsigned char [2] - skip MD4 tests if it is unsupported by OpenSSL - the patch does not change behavior under OpenSSL version != 3 - the patch just fixes build under OpenSSL 3.0 and doesn't update deprecated code or behavior 1. https://wiki.openssl.org/index.php/OpenSSL_3.0#Upgrading_from_the_OpenSSL_2.0_FIPS_Object_Module 2. https://www.openssl.org/docs/man3.0/man3/X509_check_host.html --- fips.go | 13 +++++++++++++ hostname.go | 32 ++++++++++++++++++++------------ md4_test.go | 18 ++++++++++++++++++ 3 files changed, 51 insertions(+), 12 deletions(-) diff --git a/fips.go b/fips.go index f65e14d3..b15b9bf0 100644 --- a/fips.go +++ b/fips.go @@ -16,16 +16,29 @@ package openssl /* #include + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + int FIPS_mode_set(int ONOFF) { + return 0; + } +#endif + */ import "C" +import "errors" import "runtime" // FIPSModeSet enables a FIPS 140-2 validated mode of operation. // https://wiki.openssl.org/index.php/FIPS_mode_set() +// This call has been deleted from OpenSSL 3.0. func FIPSModeSet(mode bool) error { runtime.LockOSThread() defer runtime.UnlockOSThread() + if C.OPENSSL_VERSION_NUMBER >= 0x30000000 { + return errors.New("FIPS_mode_set() has been deleted from OpenSSL 3.0") + } + var r C.int if mode { r = C.FIPS_mode_set(1) diff --git a/hostname.go b/hostname.go index 0fae97fb..9ef4ba29 100644 --- a/hostname.go +++ b/hostname.go @@ -17,18 +17,26 @@ package openssl /* #include #include -#include +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + #include + typedef const char x509char; +#else + #include -#ifndef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT -#define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT 0x1 -#define X509_CHECK_FLAG_NO_WILDCARDS 0x2 + #ifndef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT + #define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT 0x1 + #define X509_CHECK_FLAG_NO_WILDCARDS 0x2 -extern int X509_check_host(X509 *x, const unsigned char *chk, size_t chklen, - unsigned int flags, char **peername); -extern int X509_check_email(X509 *x, const unsigned char *chk, size_t chklen, - unsigned int flags); -extern int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen, - unsigned int flags); + extern int X509_check_host(X509 *x, const unsigned char *chk, size_t chklen, + unsigned int flags, char **peername); + extern int X509_check_email(X509 *x, const unsigned char *chk, size_t chklen, + unsigned int flags); + extern int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen, + unsigned int flags); + typedef const unsigned char x509char; + #else + typedef const char x509char; + #endif #endif */ import "C" @@ -59,7 +67,7 @@ func (c *Certificate) CheckHost(host string, flags CheckFlags) error { chost := unsafe.Pointer(C.CString(host)) defer C.free(chost) - rv := C.X509_check_host(c.x, (*C.uchar)(chost), C.size_t(len(host)), + rv := C.X509_check_host(c.x, (*C.x509char)(chost), C.size_t(len(host)), C.uint(flags), nil) if rv > 0 { return nil @@ -78,7 +86,7 @@ func (c *Certificate) CheckHost(host string, flags CheckFlags) error { func (c *Certificate) CheckEmail(email string, flags CheckFlags) error { cemail := unsafe.Pointer(C.CString(email)) defer C.free(cemail) - rv := C.X509_check_email(c.x, (*C.uchar)(cemail), C.size_t(len(email)), + rv := C.X509_check_email(c.x, (*C.x509char)(cemail), C.size_t(len(email)), C.uint(flags)) if rv > 0 { return nil diff --git a/md4_test.go b/md4_test.go index b31c7e64..9041ebfe 100644 --- a/md4_test.go +++ b/md4_test.go @@ -56,7 +56,19 @@ var md4Examples = []struct{ out, in string }{ {"6e593341e62194911d5cc31e39835f27", "c5e4bc73821faa34adf9468441ffd97520a96cd5debda4d51edcaaf2b23fbd"}, } +func skipIfMD4Unsupported(t testing.TB) { + t.Helper() + + hash, err := NewMD4Hash() + if err != nil { + t.Skip("MD4 is not supported by OpenSSL") + } + hash.Close() +} + func TestMD4Examples(t *testing.T) { + skipIfMD4Unsupported(t) + for _, ex := range md4Examples { buf, err := hex.DecodeString(ex.in) if err != nil { @@ -75,6 +87,8 @@ func TestMD4Examples(t *testing.T) { } func TestMD4Writer(t *testing.T) { + skipIfMD4Unsupported(t) + ohash, err := NewMD4Hash() if err != nil { t.Fatal(err) @@ -120,9 +134,13 @@ func benchmarkMD4(b *testing.B, length int64, fn md4func) { } func BenchmarkMD4Large_openssl(b *testing.B) { + skipIfMD4Unsupported(b) + benchmarkMD4(b, 1024*1024, func(buf []byte) { MD4(buf) }) } func BenchmarkMD4Small_openssl(b *testing.B) { + skipIfMD4Unsupported(b) + benchmarkMD4(b, 1, func(buf []byte) { MD4(buf) }) } From e5e193b4dc3563e742f1c990a59ce57ee07d4e5e Mon Sep 17 00:00:00 2001 From: Oleg Jukovec Date: Wed, 29 Jun 2022 15:39:08 +0300 Subject: [PATCH 2/3] Add Ubuntu 22.04 runner to GitHub Actions go test workflow --- .github/workflows/go-test-ubuntu-22.04.yml | 69 ++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 .github/workflows/go-test-ubuntu-22.04.yml diff --git a/.github/workflows/go-test-ubuntu-22.04.yml b/.github/workflows/go-test-ubuntu-22.04.yml new file mode 100644 index 00000000..cb086365 --- /dev/null +++ b/.github/workflows/go-test-ubuntu-22.04.yml @@ -0,0 +1,69 @@ +# See: +# https://github.com/libp2p/go-openssl/pull/25 +# https://github.com/protocol/.github/issues/349 +# for details. +on: [push, pull_request] +name: Go Test + +jobs: + unit: + strategy: + fail-fast: false + matrix: + os: [ "ubuntu-22.04" ] + go: [ "1.17.x", "1.18.x" ] + env: + COVERAGES: "" + runs-on: ${{ matrix.os }} + name: ${{ matrix.os }} (go ${{ matrix.go }}) + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + - uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go }} + - name: Go information + run: | + go version + go env + - name: Use msys2 on windows + if: startsWith(matrix.os, 'windows') + shell: bash + # The executable for msys2 is also called bash.cmd + # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md#shells + # If we prepend its location to the PATH + # subsequent 'shell: bash' steps will use msys2 instead of gitbash + run: echo "C:/msys64/usr/bin" >> $GITHUB_PATH + - name: Run repo-specific setup + uses: ./.github/actions/go-test-setup + if: hashFiles('./.github/actions/go-test-setup') != '' + - name: Run tests + uses: protocol/multiple-go-modules@v1.2 + with: + # Use -coverpkg=./..., so that we include cross-package coverage. + # If package ./A imports ./B, and ./A's tests also cover ./B, + # this means ./B's coverage will be significantly higher than 0%. + run: go test -v -coverprofile=module-coverage.txt -coverpkg=./... ./... + - name: Run tests (32 bit) + if: startsWith(matrix.os, 'macos') == false # can't run 32 bit tests on OSX. + uses: protocol/multiple-go-modules@v1.2 + env: + GOARCH: 386 + with: + run: | + export "PATH=${{ env.PATH_386 }}:$PATH" + go test -v ./... + - name: Run tests with race detector + if: startsWith(matrix.os, 'ubuntu') # speed things up. Windows and OSX VMs are slow + uses: protocol/multiple-go-modules@v1.2 + with: + run: go test -v -race ./... + - name: Collect coverage files + shell: bash + run: echo "COVERAGES=$(find . -type f -name 'module-coverage.txt' | tr -s '\n' ',' | sed 's/,$//')" >> $GITHUB_ENV + - name: Upload coverage to Codecov + uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 + with: + files: '${{ env.COVERAGES }}' + env_vars: OS=${{ matrix.os }}, GO=${{ matrix.go }} From b87b660e7b94caf58c381a38dfb1c290fa7fd82d Mon Sep 17 00:00:00 2001 From: Oleg Jukovec Date: Thu, 30 Jun 2022 16:38:07 +0300 Subject: [PATCH 3/3] Fix flaky tests on Ubuntu 22.04 It is necessary to handle OpenSSL errors very carefully. Otherwise, errors may appear in unexpected places. For example, we didn't catch an error from EVP_DigestInit_ex() and it appears sometimes in conn.go: func (c *Conn) getErrorHandler(rv C.int, errno error) func() error { errcode := C.SSL_get_error(c.ssl, rv) // <- here --- md4.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/md4.go b/md4.go index 7977af1d..95d9d2d2 100644 --- a/md4.go +++ b/md4.go @@ -51,8 +51,11 @@ func (s *MD4Hash) Close() { } func (s *MD4Hash) Reset() error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() if C.X_EVP_DigestInit_ex(s.ctx, C.X_EVP_md4(), engineRef(s.engine)) != 1 { - return errors.New("openssl: md4: cannot init digest ctx") + return errors.New("openssl: md4: cannot init digest ctx: " + + errorFromErrorQueue().Error()) } return nil }