Skip to content

Commit 136f75d

Browse files
authored
Use Go strings instead of C.CString (#252)
* use Go strings instead of C.CString * clarify cString readonly
1 parent eec9ccf commit 136f75d

14 files changed

+142
-114
lines changed

const.go

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package openssl
2+
3+
import "C"
4+
import "unsafe"
5+
6+
// cString is a null-terminated string,
7+
// akin to C's char*.
8+
type cString string
9+
10+
// str returns the string value.
11+
func (s cString) str() string {
12+
return string(s)
13+
}
14+
15+
// ptr returns a pointer to the string data.
16+
// It panics if the string is not null-terminated.
17+
//
18+
// The memory pointed to by the returned pointer should
19+
// not be modified and it must only be passed to
20+
// "const char*" parameters. Any attempt to modify it
21+
// will result in a runtime panic, as Go strings are
22+
// allocated in read-only memory.
23+
func (s cString) ptr() *C.char {
24+
if len(s) == 0 {
25+
return nil
26+
}
27+
if s[len(s)-1] != 0 {
28+
panic("must be null-terminated")
29+
}
30+
return (*C.char)(unsafe.Pointer(unsafe.StringData(string(s))))
31+
}
32+
33+
const (
34+
// Provider names
35+
_ProviderNameFips cString = "fips\x00"
36+
_ProviderNameDefault cString = "default\x00"
37+
38+
// Property strings
39+
_PropFIPSYes cString = "fips=yes\x00"
40+
_PropFIPSNo cString = "-fips\x00"
41+
42+
// Key types
43+
_KeyTypeRSA cString = "RSA\x00"
44+
_KeyTypeEC cString = "EC\x00"
45+
_KeyTypeED25519 cString = "ED25519\x00"
46+
47+
// Digest Names
48+
_DigestNameSHA2_256 cString = "SHA2-256\x00"
49+
50+
// KDF names
51+
_OSSL_KDF_NAME_HKDF cString = "HKDF\x00"
52+
_OSSL_KDF_NAME_PBKDF2 cString = "PBKDF2\x00"
53+
_OSSL_KDF_NAME_TLS1_PRF cString = "TLS1-PRF\x00"
54+
_OSSL_MAC_NAME_HMAC cString = "HMAC\x00"
55+
56+
// KDF parameters
57+
_OSSL_KDF_PARAM_DIGEST cString = "digest\x00"
58+
_OSSL_KDF_PARAM_SECRET cString = "secret\x00"
59+
_OSSL_KDF_PARAM_SEED cString = "seed\x00"
60+
_OSSL_KDF_PARAM_KEY cString = "key\x00"
61+
_OSSL_KDF_PARAM_INFO cString = "info\x00"
62+
_OSSL_KDF_PARAM_SALT cString = "salt\x00"
63+
_OSSL_KDF_PARAM_MODE cString = "mode\x00"
64+
65+
// PKEY parameters
66+
_OSSL_PKEY_PARAM_PUB_KEY cString = "pub\x00"
67+
_OSSL_PKEY_PARAM_PRIV_KEY cString = "priv\x00"
68+
_OSSL_PKEY_PARAM_GROUP_NAME cString = "group\x00"
69+
_OSSL_PKEY_PARAM_EC_PUB_X cString = "qx\x00"
70+
_OSSL_PKEY_PARAM_EC_PUB_Y cString = "qy\x00"
71+
_OSSL_PKEY_PARAM_FFC_PBITS cString = "pbits\x00"
72+
_OSSL_PKEY_PARAM_FFC_QBITS cString = "qbits\x00"
73+
_OSSL_PKEY_PARAM_RSA_N cString = "n\x00"
74+
_OSSL_PKEY_PARAM_RSA_E cString = "e\x00"
75+
_OSSL_PKEY_PARAM_RSA_D cString = "d\x00"
76+
_OSSL_PKEY_PARAM_FFC_P cString = "p\x00"
77+
_OSSL_PKEY_PARAM_FFC_Q cString = "q\x00"
78+
_OSSL_PKEY_PARAM_FFC_G cString = "g\x00"
79+
_OSSL_PKEY_PARAM_RSA_FACTOR1 cString = "rsa-factor1\x00"
80+
_OSSL_PKEY_PARAM_RSA_FACTOR2 cString = "rsa-factor2\x00"
81+
_OSSL_PKEY_PARAM_RSA_EXPONENT1 cString = "rsa-exponent1\x00"
82+
_OSSL_PKEY_PARAM_RSA_EXPONENT2 cString = "rsa-exponent2\x00"
83+
_OSSL_PKEY_PARAM_RSA_COEFFICIENT1 cString = "rsa-coefficient1\x00"
84+
85+
// MAC parameters
86+
_OSSL_MAC_PARAM_DIGEST cString = "digest\x00"
87+
)

dsa.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,9 @@ func GenerateParametersDSA(l, n int) (DSAParameters, error) {
9898
C.go_openssl_BN_free(q)
9999
C.go_openssl_BN_free(g)
100100
}()
101-
if C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_FFC_P, &p) != 1 ||
102-
C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_FFC_Q, &q) != 1 ||
103-
C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_FFC_G, &g) != 1 {
101+
if C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_FFC_P.ptr(), &p) != 1 ||
102+
C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_FFC_Q.ptr(), &q) != 1 ||
103+
C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_FFC_G.ptr(), &g) != 1 {
104104
return DSAParameters{}, newOpenSSLError("EVP_PKEY_get_bn_param")
105105
}
106106
default:
@@ -159,8 +159,8 @@ func GenerateKeyDSA(params DSAParameters) (x, y BigInt, err error) {
159159
C.go_openssl_BN_clear_free(bx)
160160
C.go_openssl_BN_free(by)
161161
}()
162-
if C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_PUB_KEY, &by) != 1 ||
163-
C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_PRIV_KEY, &bx) != 1 {
162+
if C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_PUB_KEY.ptr(), &by) != 1 ||
163+
C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_PRIV_KEY.ptr(), &bx) != 1 {
164164
return nil, nil, newOpenSSLError("EVP_PKEY_get_bn_param")
165165
}
166166
default:

ecdh.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ func GenerateKeyECDH(curve string) (*PrivateKeyECDH, []byte, error) {
280280
return nil, nil, newOpenSSLError("EC_KEY_get0_private_key")
281281
}
282282
case 3:
283-
if C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_PRIV_KEY, &priv) != 1 {
283+
if C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_PRIV_KEY.ptr(), &priv) != 1 {
284284
return nil, nil, newOpenSSLError("EVP_PKEY_get_bn_param")
285285
}
286286
defer C.go_openssl_BN_clear_free(priv)

ecdsa.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,9 @@ func GenerateKeyECDSA(curve string) (x, y, d BigInt, err error) {
9191
// Get Z. We don't need to free it, get0 does not increase the reference count.
9292
bd = C.go_openssl_EC_KEY_get0_private_key(key)
9393
case 3:
94-
if C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_EC_PUB_X, &bx) != 1 ||
95-
C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_EC_PUB_Y, &by) != 1 ||
96-
C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_PRIV_KEY, &bd) != 1 {
94+
if C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_EC_PUB_X.ptr(), &bx) != 1 ||
95+
C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_EC_PUB_Y.ptr(), &by) != 1 ||
96+
C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_PRIV_KEY.ptr(), &bd) != 1 {
9797
return nil, nil, nil, newOpenSSLError("EVP_PKEY_get_bn_param")
9898
}
9999
defer C.go_openssl_BN_clear_free(bd)

ed25519.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ var supportsEd25519 = sync.OnceValue(func() bool {
3636
}
3737
}
3838
case 3:
39-
sig := C.go_openssl_EVP_SIGNATURE_fetch(nil, keyTypeED25519, nil)
39+
sig := C.go_openssl_EVP_SIGNATURE_fetch(nil, _KeyTypeED25519.ptr(), nil)
4040
if sig != nil {
4141
C.go_openssl_EVP_SIGNATURE_free(sig)
4242
return true

evp.go

+3-9
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,6 @@ import (
1313
"unsafe"
1414
)
1515

16-
var (
17-
keyTypeRSA = C.CString("RSA")
18-
keyTypeEC = C.CString("EC")
19-
keyTypeED25519 = C.CString("ED25519")
20-
)
21-
2216
// cacheMD is a cache of crypto.Hash to GO_EVP_MD_PTR.
2317
var cacheMD sync.Map
2418

@@ -201,11 +195,11 @@ func generateEVPPKey(id C.int, bits int, curve string) (C.GO_EVP_PKEY_PTR, error
201195
case 3:
202196
switch id {
203197
case C.GO_EVP_PKEY_RSA:
204-
pkey = C.go_openssl_EVP_PKEY_Q_keygen_RSA(nil, nil, keyTypeRSA, C.size_t(bits))
198+
pkey = C.go_openssl_EVP_PKEY_Q_keygen_RSA(nil, nil, _KeyTypeRSA.ptr(), C.size_t(bits))
205199
case C.GO_EVP_PKEY_EC:
206-
pkey = C.go_openssl_EVP_PKEY_Q_keygen_EC(nil, nil, keyTypeEC, C.go_openssl_OBJ_nid2sn(curveNID(curve)))
200+
pkey = C.go_openssl_EVP_PKEY_Q_keygen_EC(nil, nil, _KeyTypeEC.ptr(), C.go_openssl_OBJ_nid2sn(curveNID(curve)))
207201
case C.GO_EVP_PKEY_ED25519:
208-
pkey = C.go_openssl_EVP_PKEY_Q_keygen(nil, nil, keyTypeED25519)
202+
pkey = C.go_openssl_EVP_PKEY_Q_keygen(nil, nil, _KeyTypeED25519.ptr())
209203
default:
210204
panic("unsupported key type '" + strconv.Itoa(int(id)) + "'")
211205
}

hkdf.go

+1-3
Original file line numberDiff line numberDiff line change
@@ -239,9 +239,7 @@ func (c *hkdf3) finalize() {
239239
var fetchHKDF3 = sync.OnceValues(func() (C.GO_EVP_KDF_PTR, error) {
240240
checkMajorVersion(3)
241241

242-
name := C.CString("HKDF")
243-
kdf := C.go_openssl_EVP_KDF_fetch(nil, name, nil)
244-
C.free(unsafe.Pointer(name))
242+
kdf := C.go_openssl_EVP_KDF_fetch(nil, _OSSL_KDF_NAME_HKDF.ptr(), nil)
245243
if kdf == nil {
246244
return nil, newOpenSSLError("EVP_KDF_fetch")
247245
}

hmac.go

+10-14
Original file line numberDiff line numberDiff line change
@@ -88,27 +88,26 @@ func newHMAC1(key []byte, md C.GO_EVP_MD_PTR) hmacCtx1 {
8888

8989
var hmacDigestsSupported sync.Map
9090
var fetchHMAC3 = sync.OnceValue(func() C.GO_EVP_MAC_PTR {
91-
name := C.CString("HMAC")
92-
mac := C.go_openssl_EVP_MAC_fetch(nil, name, nil)
93-
C.free(unsafe.Pointer(name))
91+
mac := C.go_openssl_EVP_MAC_fetch(nil, _OSSL_MAC_NAME_HMAC.ptr(), nil)
9492
if mac == nil {
9593
panic("openssl: HMAC not supported")
9694
}
9795
return mac
9896
})
9997

100-
func buildHMAC3Params(digest *C.char) (C.GO_OSSL_PARAM_PTR, error) {
98+
func buildHMAC3Params(md C.GO_EVP_MD_PTR) (C.GO_OSSL_PARAM_PTR, error) {
10199
bld, err := newParamBuilder()
102100
if err != nil {
103101
return nil, err
104102
}
105103
defer bld.finalize()
106-
bld.addUTF8String(_OSSL_MAC_PARAM_DIGEST, digest, 0)
104+
bld.addUTF8String(_OSSL_MAC_PARAM_DIGEST, C.go_openssl_EVP_MD_get0_name(md), 0)
107105
return bld.build()
108106
}
109107

110-
func isHMAC3DigestSupported(digest string) bool {
111-
if v, ok := hmacDigestsSupported.Load(digest); ok {
108+
func isHMAC3DigestSupported(md C.GO_EVP_MD_PTR) bool {
109+
nid := C.go_openssl_EVP_MD_get_type(md)
110+
if v, ok := hmacDigestsSupported.Load(nid); ok {
112111
return v.(bool)
113112
}
114113
ctx := C.go_openssl_EVP_MAC_CTX_new(fetchHMAC3())
@@ -117,29 +116,26 @@ func isHMAC3DigestSupported(digest string) bool {
117116
}
118117
defer C.go_openssl_EVP_MAC_CTX_free(ctx)
119118

120-
cdigest := C.CString(digest)
121-
defer C.free(unsafe.Pointer(cdigest))
122-
params, err := buildHMAC3Params(cdigest)
119+
params, err := buildHMAC3Params(md)
123120
if err != nil {
124121
panic(err)
125122
}
126123
defer C.go_openssl_OSSL_PARAM_free(params)
127124

128125
supported := C.go_openssl_EVP_MAC_CTX_set_params(ctx, params) != 0
129-
hmacDigestsSupported.Store(digest, supported)
126+
hmacDigestsSupported.Store(nid, supported)
130127
return supported
131128
}
132129

133130
func newHMAC3(key []byte, md C.GO_EVP_MD_PTR) hmacCtx3 {
134-
digest := C.go_openssl_EVP_MD_get0_name(md)
135-
if !isHMAC3DigestSupported(C.GoString(digest)) {
131+
if !isHMAC3DigestSupported(md) {
136132
// The digest is not supported by the HMAC provider.
137133
// Don't panic here so the Go standard library to
138134
// fall back to the Go implementation.
139135
// See https://github.com/golang-fips/openssl/issues/153.
140136
return hmacCtx3{}
141137
}
142-
params, err := buildHMAC3Params(digest)
138+
params, err := buildHMAC3Params(md)
143139
if err != nil {
144140
panic(err)
145141
}

openssl.go

+12-21
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,6 @@ func VersionText() string {
9999
return C.GoString(C.go_openssl_OpenSSL_version(0))
100100
}
101101

102-
var (
103-
providerNameFips = C.CString("fips")
104-
providerNameDefault = C.CString("default")
105-
propFIPS = C.CString("fips=yes")
106-
propNoFIPS = C.CString("-fips")
107-
108-
algorithmSHA256 = C.CString("SHA2-256")
109-
)
110-
111102
// FIPS returns true if OpenSSL is running in FIPS mode and there is
112103
// a provider available that supports FIPS. It returns false otherwise.
113104
func FIPS() bool {
@@ -128,7 +119,7 @@ func FIPS() bool {
128119
// but that is highly unlikely because SHA-256 is one of the most common algorithms and fundamental to many cryptographic operations.
129120
// It also has a small chance of false positive if the FIPS provider implements the SHA-256 algorithm but not the other algorithms
130121
// used by the caller application, but that is also unlikely because the FIPS provider should provide all common algorithms.
131-
return proveSHA256(nil)
122+
return proveSHA256("")
132123
default:
133124
panic(errUnsupportedVersion())
134125
}
@@ -155,11 +146,11 @@ func FIPSCapable() bool {
155146
if vMajor == 3 {
156147
// Load the provider with and without the `fips=yes` query.
157148
// If the providers are the same, then the default provider is FIPS-capable.
158-
provFIPS := sha256Provider(propFIPS)
149+
provFIPS := sha256Provider(_ProviderNameFips)
159150
if provFIPS == nil {
160151
return false
161152
}
162-
provDefault := sha256Provider(nil)
153+
provDefault := sha256Provider("")
163154
return provFIPS == provDefault
164155
}
165156
return false
@@ -198,18 +189,18 @@ func SetFIPS(enable bool) error {
198189
}
199190
return nil
200191
case 3:
201-
var shaProps, provName *C.char
192+
var shaProps, provName cString
202193
if enable {
203-
shaProps = propFIPS
204-
provName = providerNameFips
194+
shaProps = _PropFIPSYes
195+
provName = _ProviderNameFips
205196
} else {
206-
shaProps = propNoFIPS
207-
provName = providerNameDefault
197+
shaProps = _PropFIPSNo
198+
provName = _ProviderNameDefault
208199
}
209200
if !proveSHA256(shaProps) {
210201
// There is no provider available that supports the desired FIPS mode.
211202
// Try to load the built-in provider associated with the given mode.
212-
if C.go_openssl_OSSL_PROVIDER_try_load(nil, provName, 1) == nil {
203+
if C.go_openssl_OSSL_PROVIDER_try_load(nil, provName.ptr(), 1) == nil {
213204
// The built-in provider was not loaded successfully, we can't enable FIPS mode.
214205
C.go_openssl_ERR_clear_error()
215206
return errors.New("openssl: FIPS mode not supported by any provider")
@@ -226,8 +217,8 @@ func SetFIPS(enable bool) error {
226217

227218
// sha256Provider returns the provider for the SHA-256 algorithm
228219
// using the given properties.
229-
func sha256Provider(props *C.char) C.GO_OSSL_PROVIDER_PTR {
230-
md := C.go_openssl_EVP_MD_fetch(nil, algorithmSHA256, props)
220+
func sha256Provider(props cString) C.GO_OSSL_PROVIDER_PTR {
221+
md := C.go_openssl_EVP_MD_fetch(nil, _DigestNameSHA2_256.ptr(), props.ptr())
231222
if md == nil {
232223
C.go_openssl_ERR_clear_error()
233224
return nil
@@ -238,7 +229,7 @@ func sha256Provider(props *C.char) C.GO_OSSL_PROVIDER_PTR {
238229

239230
// proveSHA256 checks if the SHA-256 algorithm is available
240231
// using the given properties.
241-
func proveSHA256(props *C.char) bool {
232+
func proveSHA256(props cString) bool {
242233
return sha256Provider(props) != nil
243234
}
244235

0 commit comments

Comments
 (0)