Skip to content

Commit b136e57

Browse files
authored
Merge pull request #263 from golang-fips/init2
Improve CheckVersion resource cleanup
2 parents 0080156 + f8f0cd3 commit b136e57

File tree

2 files changed

+72
-64
lines changed

2 files changed

+72
-64
lines changed

hmac.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,13 +182,11 @@ func (h *opensslHMAC) Reset() {
182182
}
183183

184184
func (h *opensslHMAC) finalize() {
185-
switch vMajor {
186-
case 1:
185+
if h.ctx1.ctx != nil {
187186
go_openssl_HMAC_CTX_free(h.ctx1.ctx)
188-
case 3:
187+
}
188+
if h.ctx3.ctx != nil {
189189
go_openssl_EVP_MAC_CTX_free(h.ctx3.ctx)
190-
default:
191-
panic(errUnsupportedVersion())
192190
}
193191
}
194192

init.go

Lines changed: 69 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,26 @@ import (
1111
// osslHandle is the handle to the OpenSSL shared library loaded in the [Init] function.
1212
var osslHandle unsafe.Pointer
1313

14-
// opensslInit loads and initialize OpenSSL.
15-
// If successful, it returns the major and minor OpenSSL version
16-
// as reported by the OpenSSL API.
14+
// opensslInit loads and initializes OpenSSL.
1715
//
18-
// See Init() for details about file.
16+
// See [Init] for details about file.
1917
func opensslInit(file string) error {
2018
// Load the OpenSSL shared library using dlopen.
21-
handle, err := openLibrary(file)
19+
handle, close, err := openLibrary(file)
2220
if err != nil {
2321
return err
2422
}
2523

26-
loadOpenSSLFuncs(handle)
24+
mkcgoLoad_(handle)
25+
if vMajor == 1 {
26+
mkcgoLoad_legacy_1(handle)
27+
if vPatch == 1 {
28+
mkcgoLoad_111(handle)
29+
}
30+
} else {
31+
mkcgoLoad_111(handle)
32+
mkcgoLoad_3(handle)
33+
}
2734

2835
// Initialize OpenSSL.
2936
go_openssl_OPENSSL_init()
@@ -33,84 +40,87 @@ func opensslInit(file string) error {
3340
_OPENSSL_INIT_LOAD_CONFIG|
3441
_OPENSSL_INIT_LOAD_CRYPTO_STRINGS,
3542
nil); err != nil {
36-
dlclose(handle)
43+
close()
3744
return err
3845
}
3946
osslHandle = handle
4047
return nil
4148
}
4249

43-
// loadFuncs loads and initialize the OpenSSL functions.
44-
// See shims.go for the complete list of supported functions.
45-
func loadOpenSSLFuncs(handle unsafe.Pointer) {
46-
mkcgoLoad_(handle)
47-
if vMajor == 1 {
48-
mkcgoLoad_legacy_1(handle)
49-
if vPatch == 1 {
50-
mkcgoLoad_111(handle)
51-
}
52-
} else {
53-
mkcgoLoad_111(handle)
54-
mkcgoLoad_3(handle)
55-
}
56-
}
57-
5850
// initForCheckVersion loads and initialize only the
5951
// functions required in [CheckVersion].
60-
// It returns a function that must be called to release the resources.
61-
// The function leaves all the global variables in the same state as they were
62-
// before the call.
52+
// It returns a close function that must be called to release the resources.
53+
//
54+
// This function modifies the vMajor, vMinor, and vPatch global variables as
55+
// well as other internal global variables that facilitate OpenSSL calls.
56+
//
57+
// If the function succeeds, calling the close function restores the previous
58+
// state of the global variables. If it fails, the global variables are restored
59+
// before returning.
6360
func initForCheckVersion(file string) (func(), error) {
64-
// This function can be called when the
6561
prevMajor, prevMinor, prevPatch := vMajor, vMinor, vPatch
66-
// Load the OpenSSL shared library using dlopen.
67-
handle, err := openLibrary(file)
68-
if err != nil {
62+
restoreVersion := func() {
6963
vMajor, vMinor, vPatch = prevMajor, prevMinor, prevPatch
64+
}
65+
handle, close, err := openLibrary(file)
66+
if err != nil {
67+
restoreVersion()
7068
return nil, err
7169
}
72-
73-
switch vMajor {
74-
case 1:
75-
mkcgoLoad_init_1(handle)
76-
case 3:
77-
mkcgoLoad_init_3(handle)
78-
default:
79-
// We shouldn't get here: openLibrary should have already returned an error.
80-
panic(errUnsupportedVersion())
70+
initFuncs := func() (loadX func(unsafe.Pointer), unloadX func()) {
71+
switch vMajor {
72+
case 1:
73+
loadX = mkcgoLoad_init_1
74+
unloadX = mkcgoUnload_init_1
75+
case 3:
76+
loadX = mkcgoLoad_init_3
77+
unloadX = mkcgoUnload_init_3
78+
default:
79+
// We shouldn't get here: openLibrary should have already returned an error.
80+
panic(errUnsupportedVersion())
81+
}
82+
return
8183
}
84+
loadX, unloadX := initFuncs()
85+
loadX(handle)
8286
return func() {
83-
dlclose(handle)
84-
// Undo all the changes made in this function.
85-
mkcgoUnload_version()
86-
mkcgoUnload_init_1()
87-
mkcgoUnload_init_3()
88-
vMajor, vMinor, vPatch = prevMajor, prevMinor, prevPatch
87+
restoreVersion()
88+
close()
89+
unloadX()
8990
if osslHandle != nil {
90-
loadOpenSSLFuncs(osslHandle)
91+
// If osslHandle is not nil, it means that the library was already loaded
92+
// and initialized. In this case, we need to reload the functions from
93+
// the original handle.
94+
loadX, _ = initFuncs()
95+
loadX(osslHandle)
9196
}
9297
}, nil
9398
}
9499

95100
// openLibrary loads and initialize the version of OpenSSL.
96-
func openLibrary(file string) (unsafe.Pointer, error) {
97-
handle, err := dlopen(file)
101+
// It returns the handle to the OpenSSL shared library
102+
// and a function that can be called to release the resources.
103+
func openLibrary(file string) (handle unsafe.Pointer, close func(), err error) {
104+
vMajor, vMinor, vPatch = 0, 0, 0
105+
handle, err = dlopen(file)
98106
if err != nil {
99-
return nil, err
107+
return nil, nil, err
100108
}
101-
if err := initVersion(handle); err != nil {
102-
return nil, err
103-
}
104-
return handle, nil
105-
}
106-
107-
func initVersion(handle unsafe.Pointer) error {
108-
vMajor, vMinor, vPatch = 0, 0, 0
109109
// Retrieve the loaded OpenSSL version and check if it is supported.
110110
// Notice that major and minor could not match with the version parameter
111111
// in case the name of the shared library file differs from the OpenSSL
112112
// version it contains.
113113
mkcgoLoad_version(handle)
114+
close = func() {
115+
dlclose(handle)
116+
mkcgoUnload_version()
117+
}
118+
defer func() {
119+
if err != nil {
120+
close()
121+
}
122+
}()
123+
114124
if go_openssl_OPENSSL_version_major_Available() &&
115125
go_openssl_OPENSSL_version_minor_Available() &&
116126
go_openssl_OPENSSL_version_patch_Available() {
@@ -125,7 +135,7 @@ func initVersion(handle unsafe.Pointer) error {
125135
vMinor = uint(ver >> 20 & 0xFF)
126136
vPatch = uint(ver >> 12 & 0xFF)
127137
} else {
128-
return errors.New("openssl: version not available")
138+
return handle, nil, errors.New("openssl: version not available")
129139
}
130140
var supported bool
131141
if vMajor == 1 {
@@ -135,7 +145,7 @@ func initVersion(handle unsafe.Pointer) error {
135145
supported = true
136146
}
137147
if !supported {
138-
return errUnsupportedVersion()
148+
return handle, nil, errUnsupportedVersion()
139149
}
140-
return nil
150+
return handle, close, nil
141151
}

0 commit comments

Comments
 (0)