From da23b0aee81c8a6a2c36a6c64f7ca963faa84854 Mon Sep 17 00:00:00 2001 From: qmuntal Date: Thu, 20 Feb 2025 15:04:32 +0100 Subject: [PATCH 1/2] use Go strings instead of C.CString --- const.go | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ dsa.go | 10 +++---- ecdh.go | 2 +- ecdsa.go | 6 ++-- ed25519.go | 2 +- evp.go | 12 ++------ hkdf.go | 4 +-- hmac.go | 24 +++++++--------- openssl.go | 33 ++++++++-------------- params.go | 62 ++++++++++-------------------------------- pbkdf2.go | 5 +--- rsa.go | 4 +-- shims.h | 1 + tls1prf.go | 4 +-- 14 files changed, 135 insertions(+), 114 deletions(-) create mode 100644 const.go diff --git a/const.go b/const.go new file mode 100644 index 00000000..fb35dd2a --- /dev/null +++ b/const.go @@ -0,0 +1,80 @@ +package openssl + +import "C" +import "unsafe" + +// cString is a null-terminated string, +// akin to C's char*. +type cString string + +// str returns the string value. +func (s cString) str() string { + return string(s) +} + +// ptr returns a pointer to the string data. +func (s cString) ptr() *C.char { + if len(s) == 0 { + return nil + } + if s[len(s)-1] != 0 { + panic("must be null-terminated") + } + return (*C.char)(unsafe.Pointer(unsafe.StringData(string(s)))) +} + +const ( + // Provider names + _ProviderNameFips cString = "fips\x00" + _ProviderNameDefault cString = "default\x00" + + // Property strings + _PropFIPSYes cString = "fips=yes\x00" + _PropFIPSNo cString = "-fips\x00" + + // Key types + _KeyTypeRSA cString = "RSA\x00" + _KeyTypeEC cString = "EC\x00" + _KeyTypeED25519 cString = "ED25519\x00" + + // Digest Names + _DigestNameSHA2_256 cString = "SHA2-256\x00" + + // KDF names + _OSSL_KDF_NAME_HKDF cString = "HKDF\x00" + _OSSL_KDF_NAME_PBKDF2 cString = "PBKDF2\x00" + _OSSL_KDF_NAME_TLS1_PRF cString = "TLS1-PRF\x00" + _OSSL_MAC_NAME_HMAC cString = "HMAC\x00" + + // KDF parameters + _OSSL_KDF_PARAM_DIGEST cString = "digest\x00" + _OSSL_KDF_PARAM_SECRET cString = "secret\x00" + _OSSL_KDF_PARAM_SEED cString = "seed\x00" + _OSSL_KDF_PARAM_KEY cString = "key\x00" + _OSSL_KDF_PARAM_INFO cString = "info\x00" + _OSSL_KDF_PARAM_SALT cString = "salt\x00" + _OSSL_KDF_PARAM_MODE cString = "mode\x00" + + // PKEY parameters + _OSSL_PKEY_PARAM_PUB_KEY cString = "pub\x00" + _OSSL_PKEY_PARAM_PRIV_KEY cString = "priv\x00" + _OSSL_PKEY_PARAM_GROUP_NAME cString = "group\x00" + _OSSL_PKEY_PARAM_EC_PUB_X cString = "qx\x00" + _OSSL_PKEY_PARAM_EC_PUB_Y cString = "qy\x00" + _OSSL_PKEY_PARAM_FFC_PBITS cString = "pbits\x00" + _OSSL_PKEY_PARAM_FFC_QBITS cString = "qbits\x00" + _OSSL_PKEY_PARAM_RSA_N cString = "n\x00" + _OSSL_PKEY_PARAM_RSA_E cString = "e\x00" + _OSSL_PKEY_PARAM_RSA_D cString = "d\x00" + _OSSL_PKEY_PARAM_FFC_P cString = "p\x00" + _OSSL_PKEY_PARAM_FFC_Q cString = "q\x00" + _OSSL_PKEY_PARAM_FFC_G cString = "g\x00" + _OSSL_PKEY_PARAM_RSA_FACTOR1 cString = "rsa-factor1\x00" + _OSSL_PKEY_PARAM_RSA_FACTOR2 cString = "rsa-factor2\x00" + _OSSL_PKEY_PARAM_RSA_EXPONENT1 cString = "rsa-exponent1\x00" + _OSSL_PKEY_PARAM_RSA_EXPONENT2 cString = "rsa-exponent2\x00" + _OSSL_PKEY_PARAM_RSA_COEFFICIENT1 cString = "rsa-coefficient1\x00" + + // MAC parameters + _OSSL_MAC_PARAM_DIGEST cString = "digest\x00" +) diff --git a/dsa.go b/dsa.go index 151b88b0..c9313b11 100644 --- a/dsa.go +++ b/dsa.go @@ -98,9 +98,9 @@ func GenerateParametersDSA(l, n int) (DSAParameters, error) { C.go_openssl_BN_free(q) C.go_openssl_BN_free(g) }() - if C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_FFC_P, &p) != 1 || - C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_FFC_Q, &q) != 1 || - C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_FFC_G, &g) != 1 { + if C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_FFC_P.ptr(), &p) != 1 || + C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_FFC_Q.ptr(), &q) != 1 || + C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_FFC_G.ptr(), &g) != 1 { return DSAParameters{}, newOpenSSLError("EVP_PKEY_get_bn_param") } default: @@ -159,8 +159,8 @@ func GenerateKeyDSA(params DSAParameters) (x, y BigInt, err error) { C.go_openssl_BN_clear_free(bx) C.go_openssl_BN_free(by) }() - if C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_PUB_KEY, &by) != 1 || - C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_PRIV_KEY, &bx) != 1 { + if C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_PUB_KEY.ptr(), &by) != 1 || + C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_PRIV_KEY.ptr(), &bx) != 1 { return nil, nil, newOpenSSLError("EVP_PKEY_get_bn_param") } default: diff --git a/ecdh.go b/ecdh.go index ad392dca..0312a853 100644 --- a/ecdh.go +++ b/ecdh.go @@ -280,7 +280,7 @@ func GenerateKeyECDH(curve string) (*PrivateKeyECDH, []byte, error) { return nil, nil, newOpenSSLError("EC_KEY_get0_private_key") } case 3: - if C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_PRIV_KEY, &priv) != 1 { + if C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_PRIV_KEY.ptr(), &priv) != 1 { return nil, nil, newOpenSSLError("EVP_PKEY_get_bn_param") } defer C.go_openssl_BN_clear_free(priv) diff --git a/ecdsa.go b/ecdsa.go index bc5f1117..382a12c4 100644 --- a/ecdsa.go +++ b/ecdsa.go @@ -91,9 +91,9 @@ func GenerateKeyECDSA(curve string) (x, y, d BigInt, err error) { // Get Z. We don't need to free it, get0 does not increase the reference count. bd = C.go_openssl_EC_KEY_get0_private_key(key) case 3: - if C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_EC_PUB_X, &bx) != 1 || - C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_EC_PUB_Y, &by) != 1 || - C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_PRIV_KEY, &bd) != 1 { + if C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_EC_PUB_X.ptr(), &bx) != 1 || + C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_EC_PUB_Y.ptr(), &by) != 1 || + C.go_openssl_EVP_PKEY_get_bn_param(pkey, _OSSL_PKEY_PARAM_PRIV_KEY.ptr(), &bd) != 1 { return nil, nil, nil, newOpenSSLError("EVP_PKEY_get_bn_param") } defer C.go_openssl_BN_clear_free(bd) diff --git a/ed25519.go b/ed25519.go index f96db2cd..4543a229 100644 --- a/ed25519.go +++ b/ed25519.go @@ -36,7 +36,7 @@ var supportsEd25519 = sync.OnceValue(func() bool { } } case 3: - sig := C.go_openssl_EVP_SIGNATURE_fetch(nil, keyTypeED25519, nil) + sig := C.go_openssl_EVP_SIGNATURE_fetch(nil, _KeyTypeED25519.ptr(), nil) if sig != nil { C.go_openssl_EVP_SIGNATURE_free(sig) return true diff --git a/evp.go b/evp.go index 0c5a133b..99f5fce0 100644 --- a/evp.go +++ b/evp.go @@ -13,12 +13,6 @@ import ( "unsafe" ) -var ( - keyTypeRSA = C.CString("RSA") - keyTypeEC = C.CString("EC") - keyTypeED25519 = C.CString("ED25519") -) - // cacheMD is a cache of crypto.Hash to GO_EVP_MD_PTR. var cacheMD sync.Map @@ -201,11 +195,11 @@ func generateEVPPKey(id C.int, bits int, curve string) (C.GO_EVP_PKEY_PTR, error case 3: switch id { case C.GO_EVP_PKEY_RSA: - pkey = C.go_openssl_EVP_PKEY_Q_keygen_RSA(nil, nil, keyTypeRSA, C.size_t(bits)) + pkey = C.go_openssl_EVP_PKEY_Q_keygen_RSA(nil, nil, _KeyTypeRSA.ptr(), C.size_t(bits)) case C.GO_EVP_PKEY_EC: - pkey = C.go_openssl_EVP_PKEY_Q_keygen_EC(nil, nil, keyTypeEC, C.go_openssl_OBJ_nid2sn(curveNID(curve))) + pkey = C.go_openssl_EVP_PKEY_Q_keygen_EC(nil, nil, _KeyTypeEC.ptr(), C.go_openssl_OBJ_nid2sn(curveNID(curve))) case C.GO_EVP_PKEY_ED25519: - pkey = C.go_openssl_EVP_PKEY_Q_keygen(nil, nil, keyTypeED25519) + pkey = C.go_openssl_EVP_PKEY_Q_keygen(nil, nil, _KeyTypeED25519.ptr()) default: panic("unsupported key type '" + strconv.Itoa(int(id)) + "'") } diff --git a/hkdf.go b/hkdf.go index d4f8aa6a..a2f07750 100644 --- a/hkdf.go +++ b/hkdf.go @@ -239,9 +239,7 @@ func (c *hkdf3) finalize() { var fetchHKDF3 = sync.OnceValues(func() (C.GO_EVP_KDF_PTR, error) { checkMajorVersion(3) - name := C.CString("HKDF") - kdf := C.go_openssl_EVP_KDF_fetch(nil, name, nil) - C.free(unsafe.Pointer(name)) + kdf := C.go_openssl_EVP_KDF_fetch(nil, _OSSL_KDF_NAME_HKDF.ptr(), nil) if kdf == nil { return nil, newOpenSSLError("EVP_KDF_fetch") } diff --git a/hmac.go b/hmac.go index fa298bb1..65731670 100644 --- a/hmac.go +++ b/hmac.go @@ -88,27 +88,26 @@ func newHMAC1(key []byte, md C.GO_EVP_MD_PTR) hmacCtx1 { var hmacDigestsSupported sync.Map var fetchHMAC3 = sync.OnceValue(func() C.GO_EVP_MAC_PTR { - name := C.CString("HMAC") - mac := C.go_openssl_EVP_MAC_fetch(nil, name, nil) - C.free(unsafe.Pointer(name)) + mac := C.go_openssl_EVP_MAC_fetch(nil, _OSSL_MAC_NAME_HMAC.ptr(), nil) if mac == nil { panic("openssl: HMAC not supported") } return mac }) -func buildHMAC3Params(digest *C.char) (C.GO_OSSL_PARAM_PTR, error) { +func buildHMAC3Params(md C.GO_EVP_MD_PTR) (C.GO_OSSL_PARAM_PTR, error) { bld, err := newParamBuilder() if err != nil { return nil, err } defer bld.finalize() - bld.addUTF8String(_OSSL_MAC_PARAM_DIGEST, digest, 0) + bld.addUTF8String(_OSSL_MAC_PARAM_DIGEST, C.go_openssl_EVP_MD_get0_name(md), 0) return bld.build() } -func isHMAC3DigestSupported(digest string) bool { - if v, ok := hmacDigestsSupported.Load(digest); ok { +func isHMAC3DigestSupported(md C.GO_EVP_MD_PTR) bool { + nid := C.go_openssl_EVP_MD_get_type(md) + if v, ok := hmacDigestsSupported.Load(nid); ok { return v.(bool) } ctx := C.go_openssl_EVP_MAC_CTX_new(fetchHMAC3()) @@ -117,29 +116,26 @@ func isHMAC3DigestSupported(digest string) bool { } defer C.go_openssl_EVP_MAC_CTX_free(ctx) - cdigest := C.CString(digest) - defer C.free(unsafe.Pointer(cdigest)) - params, err := buildHMAC3Params(cdigest) + params, err := buildHMAC3Params(md) if err != nil { panic(err) } defer C.go_openssl_OSSL_PARAM_free(params) supported := C.go_openssl_EVP_MAC_CTX_set_params(ctx, params) != 0 - hmacDigestsSupported.Store(digest, supported) + hmacDigestsSupported.Store(nid, supported) return supported } func newHMAC3(key []byte, md C.GO_EVP_MD_PTR) hmacCtx3 { - digest := C.go_openssl_EVP_MD_get0_name(md) - if !isHMAC3DigestSupported(C.GoString(digest)) { + if !isHMAC3DigestSupported(md) { // The digest is not supported by the HMAC provider. // Don't panic here so the Go standard library to // fall back to the Go implementation. // See https://github.com/golang-fips/openssl/issues/153. return hmacCtx3{} } - params, err := buildHMAC3Params(digest) + params, err := buildHMAC3Params(md) if err != nil { panic(err) } diff --git a/openssl.go b/openssl.go index 0dad8e55..1c78b9b7 100644 --- a/openssl.go +++ b/openssl.go @@ -99,15 +99,6 @@ func VersionText() string { return C.GoString(C.go_openssl_OpenSSL_version(0)) } -var ( - providerNameFips = C.CString("fips") - providerNameDefault = C.CString("default") - propFIPS = C.CString("fips=yes") - propNoFIPS = C.CString("-fips") - - algorithmSHA256 = C.CString("SHA2-256") -) - // FIPS returns true if OpenSSL is running in FIPS mode and there is // a provider available that supports FIPS. It returns false otherwise. func FIPS() bool { @@ -128,7 +119,7 @@ func FIPS() bool { // but that is highly unlikely because SHA-256 is one of the most common algorithms and fundamental to many cryptographic operations. // It also has a small chance of false positive if the FIPS provider implements the SHA-256 algorithm but not the other algorithms // used by the caller application, but that is also unlikely because the FIPS provider should provide all common algorithms. - return proveSHA256(nil) + return proveSHA256("") default: panic(errUnsupportedVersion()) } @@ -155,11 +146,11 @@ func FIPSCapable() bool { if vMajor == 3 { // Load the provider with and without the `fips=yes` query. // If the providers are the same, then the default provider is FIPS-capable. - provFIPS := sha256Provider(propFIPS) + provFIPS := sha256Provider(_ProviderNameFips) if provFIPS == nil { return false } - provDefault := sha256Provider(nil) + provDefault := sha256Provider("") return provFIPS == provDefault } return false @@ -198,18 +189,18 @@ func SetFIPS(enable bool) error { } return nil case 3: - var shaProps, provName *C.char + var shaProps, provName cString if enable { - shaProps = propFIPS - provName = providerNameFips + shaProps = _PropFIPSYes + provName = _ProviderNameFips } else { - shaProps = propNoFIPS - provName = providerNameDefault + shaProps = _PropFIPSNo + provName = _ProviderNameDefault } if !proveSHA256(shaProps) { // There is no provider available that supports the desired FIPS mode. // Try to load the built-in provider associated with the given mode. - if C.go_openssl_OSSL_PROVIDER_try_load(nil, provName, 1) == nil { + if C.go_openssl_OSSL_PROVIDER_try_load(nil, provName.ptr(), 1) == nil { // The built-in provider was not loaded successfully, we can't enable FIPS mode. C.go_openssl_ERR_clear_error() return errors.New("openssl: FIPS mode not supported by any provider") @@ -226,8 +217,8 @@ func SetFIPS(enable bool) error { // sha256Provider returns the provider for the SHA-256 algorithm // using the given properties. -func sha256Provider(props *C.char) C.GO_OSSL_PROVIDER_PTR { - md := C.go_openssl_EVP_MD_fetch(nil, algorithmSHA256, props) +func sha256Provider(props cString) C.GO_OSSL_PROVIDER_PTR { + md := C.go_openssl_EVP_MD_fetch(nil, _DigestNameSHA2_256.ptr(), props.ptr()) if md == nil { C.go_openssl_ERR_clear_error() return nil @@ -238,7 +229,7 @@ func sha256Provider(props *C.char) C.GO_OSSL_PROVIDER_PTR { // proveSHA256 checks if the SHA-256 algorithm is available // using the given properties. -func proveSHA256(props *C.char) bool { +func proveSHA256(props cString) bool { return sha256Provider(props) != nil } diff --git a/params.go b/params.go index fa24a8cd..5fec68a6 100644 --- a/params.go +++ b/params.go @@ -9,40 +9,6 @@ import ( "unsafe" ) -var ( - // KDF parameters - _OSSL_KDF_PARAM_DIGEST = C.CString("digest") - _OSSL_KDF_PARAM_SECRET = C.CString("secret") - _OSSL_KDF_PARAM_SEED = C.CString("seed") - _OSSL_KDF_PARAM_KEY = C.CString("key") - _OSSL_KDF_PARAM_INFO = C.CString("info") - _OSSL_KDF_PARAM_SALT = C.CString("salt") - _OSSL_KDF_PARAM_MODE = C.CString("mode") - - // PKEY parameters - _OSSL_PKEY_PARAM_PUB_KEY = C.CString("pub") - _OSSL_PKEY_PARAM_PRIV_KEY = C.CString("priv") - _OSSL_PKEY_PARAM_GROUP_NAME = C.CString("group") - _OSSL_PKEY_PARAM_EC_PUB_X = C.CString("qx") - _OSSL_PKEY_PARAM_EC_PUB_Y = C.CString("qy") - _OSSL_PKEY_PARAM_FFC_PBITS = C.CString("pbits") - _OSSL_PKEY_PARAM_FFC_QBITS = C.CString("qbits") - _OSSL_PKEY_PARAM_RSA_N = C.CString("n") - _OSSL_PKEY_PARAM_RSA_E = C.CString("e") - _OSSL_PKEY_PARAM_RSA_D = C.CString("d") - _OSSL_PKEY_PARAM_FFC_P = C.CString("p") - _OSSL_PKEY_PARAM_FFC_Q = C.CString("q") - _OSSL_PKEY_PARAM_FFC_G = C.CString("g") - _OSSL_PKEY_PARAM_RSA_FACTOR1 = C.CString("rsa-factor1") - _OSSL_PKEY_PARAM_RSA_FACTOR2 = C.CString("rsa-factor2") - _OSSL_PKEY_PARAM_RSA_EXPONENT1 = C.CString("rsa-exponent1") - _OSSL_PKEY_PARAM_RSA_EXPONENT2 = C.CString("rsa-exponent2") - _OSSL_PKEY_PARAM_RSA_COEFFICIENT1 = C.CString("rsa-coefficient1") - - // MAC parameters - _OSSL_MAC_PARAM_DIGEST = C.CString("digest") -) - type bnParam struct { value C.GO_BIGNUM_PTR private bool @@ -123,47 +89,47 @@ func (b *paramBuilder) build() (C.GO_OSSL_PARAM_PTR, error) { // addUTF8String adds a NUL-terminated UTF-8 string to the builder. // size should not include the terminating NUL byte. If size is zero, then it will be calculated. -func (b *paramBuilder) addUTF8String(name *C.char, value *C.char, size C.size_t) { +func (b *paramBuilder) addUTF8String(name cString, value *C.char, size C.size_t) { if !b.check() { return } // OSSL_PARAM_BLD_push_utf8_string calculates the size if it is zero. - if C.go_openssl_OSSL_PARAM_BLD_push_utf8_string(b.bld, name, value, size) != 1 { - b.err = newOpenSSLError("OSSL_PARAM_BLD_push_utf8_string(" + C.GoString(name) + ")") + if C.go_openssl_OSSL_PARAM_BLD_push_utf8_string(b.bld, name.ptr(), value, size) != 1 { + b.err = newOpenSSLError("OSSL_PARAM_BLD_push_utf8_string(" + name.str() + ")") } } // addOctetString adds an octet string to the builder. // The value is pinned and will be unpinned when the builder is freed. -func (b *paramBuilder) addOctetString(name *C.char, value []byte) { +func (b *paramBuilder) addOctetString(name cString, value []byte) { if !b.check() { return } if len(value) != 0 { b.pinner.Pin(&value[0]) } - if C.go_openssl_OSSL_PARAM_BLD_push_octet_string(b.bld, name, unsafe.Pointer(sbase(value)), C.size_t(len(value))) != 1 { - b.err = newOpenSSLError("OSSL_PARAM_BLD_push_octet_string(" + C.GoString(name) + ")") + if C.go_openssl_OSSL_PARAM_BLD_push_octet_string(b.bld, name.ptr(), unsafe.Pointer(sbase(value)), C.size_t(len(value))) != 1 { + b.err = newOpenSSLError("OSSL_PARAM_BLD_push_octet_string(" + name.str() + ")") } } // addInt32 adds an int32 to the builder. -func (b *paramBuilder) addInt32(name *C.char, value int32) { +func (b *paramBuilder) addInt32(name cString, value int32) { if !b.check() { return } - if C.go_openssl_OSSL_PARAM_BLD_push_int32(b.bld, name, C.int32_t(value)) != 1 { - b.err = newOpenSSLError("OSSL_PARAM_BLD_push_int32(" + C.GoString(name) + ")") + if C.go_openssl_OSSL_PARAM_BLD_push_int32(b.bld, name.ptr(), C.int32_t(value)) != 1 { + b.err = newOpenSSLError("OSSL_PARAM_BLD_push_int32(" + name.str() + ")") } } // addBN adds a GO_BIGNUM_PTR to the builder. -func (b *paramBuilder) addBN(name *C.char, value C.GO_BIGNUM_PTR) { +func (b *paramBuilder) addBN(name cString, value C.GO_BIGNUM_PTR) { if !b.check() { return } - if C.go_openssl_OSSL_PARAM_BLD_push_BN(b.bld, name, value) != 1 { - b.err = newOpenSSLError("OSSL_PARAM_BLD_push_BN(" + C.GoString(name) + ")") + if C.go_openssl_OSSL_PARAM_BLD_push_BN(b.bld, name.ptr(), value) != 1 { + b.err = newOpenSSLError("OSSL_PARAM_BLD_push_BN(" + name.str() + ")") } } @@ -171,7 +137,7 @@ func (b *paramBuilder) addBN(name *C.char, value C.GO_BIGNUM_PTR) { // The slice is converted to a BIGNUM using BN_bin2bn and freed when the builder is finalized. // If private is true, the BIGNUM will be cleared with BN_clear_free, // otherwise it will be freed with BN_free. -func (b *paramBuilder) addBin(name *C.char, value []byte, private bool) { +func (b *paramBuilder) addBin(name cString, value []byte, private bool) { if !b.check() { return } @@ -192,7 +158,7 @@ func (b *paramBuilder) addBin(name *C.char, value []byte, private bool) { // The BigInt is converted using bigToBN to a BIGNUM that is freed when the builder is finalized. // If private is true, the BIGNUM will be cleared with BN_clear_free, // otherwise it will be freed with BN_free. -func (b *paramBuilder) addBigInt(name *C.char, value BigInt, private bool) { +func (b *paramBuilder) addBigInt(name cString, value BigInt, private bool) { if !b.check() { return } diff --git a/pbkdf2.go b/pbkdf2.go index 52f00d75..8a54d84d 100644 --- a/pbkdf2.go +++ b/pbkdf2.go @@ -8,7 +8,6 @@ import ( "errors" "hash" "sync" - "unsafe" ) // SupportsPBKDF2 reports whether the current OpenSSL version supports PBKDF2. @@ -30,9 +29,7 @@ func SupportsPBKDF2() bool { var fetchPBKDF2 = sync.OnceValues(func() (C.GO_EVP_KDF_PTR, error) { checkMajorVersion(3) - name := C.CString("PBKDF2") - kdf := C.go_openssl_EVP_KDF_fetch(nil, name, nil) - C.free(unsafe.Pointer(name)) + kdf := C.go_openssl_EVP_KDF_fetch(nil, _OSSL_KDF_NAME_PBKDF2.ptr(), nil) if kdf == nil { return nil, newOpenSSLError("EVP_KDF_fetch") } diff --git a/rsa.go b/rsa.go index 4b5e26c6..4747d0ab 100644 --- a/rsa.go +++ b/rsa.go @@ -45,11 +45,11 @@ func GenerateKeyRSA(bits int) (N, E, D, P, Q, Dp, Dq, Qinv BigInt, err error) { C.go_openssl_BN_clear_free(tmp) }() var err error - setBigInt := func(bi *BigInt, param *C.char) bool { + setBigInt := func(bi *BigInt, param cString) bool { if err != nil { return false } - if C.go_openssl_EVP_PKEY_get_bn_param(pkey, param, &tmp) != 1 { + if C.go_openssl_EVP_PKEY_get_bn_param(pkey, param.ptr(), &tmp) != 1 { err = newOpenSSLError("EVP_PKEY_get_bn_param failed") return false } diff --git a/shims.h b/shims.h index e799ba95..c8772bae 100644 --- a/shims.h +++ b/shims.h @@ -194,6 +194,7 @@ DEFINEFUNC_3_0(const char *, OSSL_PROVIDER_get0_name, (const GO_OSSL_PROVIDER_PT DEFINEFUNC_3_0(GO_EVP_MD_PTR, EVP_MD_fetch, (GO_OSSL_LIB_CTX_PTR ctx, const char *algorithm, const char *properties), (ctx, algorithm, properties)) \ DEFINEFUNC_3_0(void, EVP_MD_free, (GO_EVP_MD_PTR md), (md)) \ DEFINEFUNC_3_0(const char *, EVP_MD_get0_name, (const GO_EVP_MD_PTR md), (md)) \ +DEFINEFUNC_3_0(int, EVP_MD_get_type, (const GO_EVP_MD_PTR md), (md)) \ DEFINEFUNC_3_0(const GO_OSSL_PROVIDER_PTR, EVP_MD_get0_provider, (const GO_EVP_MD_PTR md), (md)) \ DEFINEFUNC_RENAMED_3_0(int, EVP_MD_get_size, EVP_MD_size, (const GO_EVP_MD_PTR md), (md)) \ DEFINEFUNC_RENAMED_3_0(int, EVP_MD_get_block_size, EVP_MD_block_size, (const GO_EVP_MD_PTR md), (md)) \ diff --git a/tls1prf.go b/tls1prf.go index 33134548..8bffacc2 100644 --- a/tls1prf.go +++ b/tls1prf.go @@ -116,9 +116,7 @@ func tls1PRF1(result, secret, label, seed []byte, md C.GO_EVP_MD_PTR) error { var fetchTLS1PRF3 = sync.OnceValues(func() (C.GO_EVP_KDF_PTR, error) { checkMajorVersion(3) - name := C.CString("TLS1-PRF") - kdf := C.go_openssl_EVP_KDF_fetch(nil, name, nil) - C.free(unsafe.Pointer(name)) + kdf := C.go_openssl_EVP_KDF_fetch(nil, _OSSL_KDF_NAME_TLS1_PRF.ptr(), nil) if kdf == nil { return nil, newOpenSSLError("EVP_KDF_fetch") } From 1ed3f5bed4b7f328f044bd2d332cd5700e6ed9ff Mon Sep 17 00:00:00 2001 From: qmuntal Date: Thu, 20 Feb 2025 15:58:52 +0100 Subject: [PATCH 2/2] clarify cString readonly --- const.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/const.go b/const.go index fb35dd2a..f2c7e84c 100644 --- a/const.go +++ b/const.go @@ -13,6 +13,13 @@ func (s cString) str() string { } // ptr returns a pointer to the string data. +// It panics if the string is not null-terminated. +// +// The memory pointed to by the returned pointer should +// not be modified and it must only be passed to +// "const char*" parameters. Any attempt to modify it +// will result in a runtime panic, as Go strings are +// allocated in read-only memory. func (s cString) ptr() *C.char { if len(s) == 0 { return nil