diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 30b174f3..a1dd903c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,120 +5,127 @@ jobs: strategy: fail-fast: false matrix: - go-version: [1.23.x, 1.24.x] - openssl-version: [1.1.0, 1.1.1, 3.0.1, 3.0.13, 3.1.5, 3.2.1, 3.3.0, 3.3.1] + go-version: [1.24.x, 1.25.x] + openssl-version: + [1.1.0, 1.1.1, 3.0.1, 3.0.13, 3.1.5, 3.2.1, 3.3.0, 3.3.1] runs-on: ubuntu-22.04 steps: - - name: Install build tools - run: sudo apt-get install -y build-essential - - name: Install Go - uses: actions/setup-go@v5 - with: - go-version: ${{ matrix.go-version }} - - name: Checkout code - uses: actions/checkout@v4 - - name: Verify go generate leaves no changes - run: | - go generate ./... - git diff --exit-code - - name: Install OpenSSL - run: sudo sh ./scripts/openssl.sh ${{ matrix.openssl-version }} - - name: Check headers - working-directory: ./cmd/checkheader - run: | - go run . --ossl-include /usr/local/src/openssl-${{ matrix.openssl-version }}/include -shim ../../internal/ossl/shims.h - - name: Set OpenSSL config and prove FIPS - run: | - sudo cp ./scripts/openssl-3.cnf /usr/local/ssl/openssl.cnf - go test -v -count 0 . | grep -q "FIPS enabled: true" - if: ${{ matrix.openssl-version == '3.0.1' }} - env: - GO_OPENSSL_VERSION_OVERRIDE: ${{ matrix.openssl-version }} - - name: Run Test - # Run each test 10 times so the garbage collector chimes in - # and exercises the multiple finalizers we use. - # This can detect use-after-free and double-free issues. - run: go test -gcflags=all=-d=checkptr -count 10 -v ./... - env: - GO_OPENSSL_VERSION_OVERRIDE: ${{ matrix.openssl-version }} - - name: Run Test with address sanitizer - run: | - ok=true - for t in $(go test ./... -list=. | grep '^Test'); do - go test ./... -gcflags=all=-d=checkptr -asan -run ^$t$ -v || ok=false - done - $ok - env: - GO_OPENSSL_VERSION_OVERRIDE: ${{ matrix.openssl-version }} + - name: Install build tools + run: sudo apt-get install -y build-essential + - name: Install Go + uses: actions/setup-go@v5 + with: + go-version: ${{ matrix.go-version }} + - name: Checkout code + uses: actions/checkout@v4 + - name: Verify go generate leaves no changes + run: | + go generate ./... + git diff --exit-code + - name: Install OpenSSL + run: sudo sh ./scripts/openssl.sh ${{ matrix.openssl-version }} + - name: Check headers + working-directory: ./cmd/checkheader + run: | + go run . --ossl-include /usr/local/src/openssl-${{ matrix.openssl-version }}/include -shim ../../internal/ossl/shims.h + - name: Set OpenSSL config and prove FIPS + run: | + sudo cp ./scripts/openssl-3.cnf /usr/local/ssl/openssl.cnf + go test -v -count 0 . | grep -q "FIPS enabled: true" + if: ${{ matrix.openssl-version == '3.0.1' }} + env: + GO_OPENSSL_VERSION_OVERRIDE: ${{ matrix.openssl-version }} + - name: Run Test + # Run each test 10 times so the garbage collector chimes in + # and exercises the multiple finalizers we use. + # This can detect use-after-free and double-free issues. + run: go test -gcflags=all=-d=checkptr -count 10 -v ./... + env: + GO_OPENSSL_VERSION_OVERRIDE: ${{ matrix.openssl-version }} + CGO_ENABLED: 0 + - name: Run Test CGO disabled + run: go test -count 10 -v ./... + env: + GO_OPENSSL_VERSION_OVERRIDE: ${{ matrix.openssl-version }} + - name: Run Test with address sanitizer + run: | + ok=true + for t in $(go test ./... -list=. | grep '^Test'); do + go test ./... -gcflags=all=-d=checkptr -asan -run ^$t$ -v || ok=false + done + $ok + env: + GO_OPENSSL_VERSION_OVERRIDE: ${{ matrix.openssl-version }} + wintest: runs-on: windows-2022 strategy: fail-fast: false matrix: - go-version: [1.22.x, 1.23.x] + go-version: [1.24.x, 1.25.x] openssl-version: [libcrypto-1_1-x64.dll, libcrypto-3-x64.dll] steps: - - name: Install Go - uses: actions/setup-go@v5 - with: - go-version: ${{ matrix.go-version }} - - name: Checkout code - uses: actions/checkout@v4 - - name: Run Test - run: go test -gcflags=all=-d=checkptr -count 10 -v ./... - env: - GO_OPENSSL_VERSION_OVERRIDE: ${{ matrix.openssl-version }} + - name: Install Go + uses: actions/setup-go@v5 + with: + go-version: ${{ matrix.go-version }} + - name: Checkout code + uses: actions/checkout@v4 + - name: Run Test + run: go test -gcflags=all=-d=checkptr -count 10 -v ./... + env: + GO_OPENSSL_VERSION_OVERRIDE: ${{ matrix.openssl-version }} + CGO_ENABLED: 1 + - name: Run Test CGO disabled + run: go test -count 10 -v ./... + env: + GO_OPENSSL_VERSION_OVERRIDE: ${{ matrix.openssl-version }} + CGO_ENABLED: 0 + mactest: strategy: fail-fast: false matrix: - go-version: [1.22.x, 1.23.x] + go-version: [1.24.x, 1.25.x] openssl-version: [/usr/local/opt/openssl@3/lib/libcrypto.3.dylib] runs-on: macos-13 steps: - - name: Install Go - uses: actions/setup-go@v5 - with: - go-version: ${{ matrix.go-version }} - - name: Checkout code - uses: actions/checkout@v4 - - name: Run Test - run: go test -gcflags=all=-d=checkptr -count 10 -v ./... - env: - GO_OPENSSL_VERSION_OVERRIDE: ${{ matrix.openssl-version }} + - name: Install Go + uses: actions/setup-go@v5 + with: + go-version: ${{ matrix.go-version }} + - name: Checkout code + uses: actions/checkout@v4 + - name: Run Test + run: go test -gcflags=all=-d=checkptr -count 10 -v ./... + env: + GO_OPENSSL_VERSION_OVERRIDE: ${{ matrix.openssl-version }} + - name: Run Test CGO disabled + run: go test -count 10 -v ./... + env: + GO_OPENSSL_VERSION_OVERRIDE: ${{ matrix.openssl-version }} + CGO_ENABLED: 0 + azurelinux: runs-on: ubuntu-latest container: mcr.microsoft.com/oss/go/microsoft/golang:1.23-azurelinux3.0 steps: - - name: Checkout code - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - name: Run Test - run: go test -v ./... + - name: Checkout code + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Run Test + run: go test -v ./... + - name: Run Test CGO disabled + run: go test -v ./... + env: + CGO_ENABLED: 0 + mariner2: runs-on: ubuntu-latest container: mcr.microsoft.com/oss/go/microsoft/golang:1.23.1-3-cbl-mariner2.0 steps: - - name: Checkout code - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - name: Run Test - run: go test -v ./... - - # Verify that golang-fips/openssl builds successfully without cgo enabled. - # - # A project can avoid attempting to build the openssl package by only - # importing it from Go files with a cgo build tag. However, this isn't always - # reasonable. In that case, we can help by making sure the openssl package - # builds successfully even without cgo. - # - # For example, the Microsoft build of Go compiles this module without cgo when - # running a cross-platform build. - # - # The golang-fips/openssl module can't do any crypto when built without cgo, - # but it exports a few simple functions and types. - cgolessbuild: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - name: Run Build - run: CGO_ENABLED=0 go build ./... + - name: Checkout code + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Run Test CGO disabled + run: go test -v ./... + env: + CGO_ENABLED: 0 diff --git a/aes.go b/aes.go index 3b3e247e..654566d2 100644 --- a/aes.go +++ b/aes.go @@ -2,7 +2,6 @@ package openssl -import "C" import ( "crypto/cipher" "errors" diff --git a/cipher.go b/cipher.go index e2b90fc0..bd1d5213 100644 --- a/cipher.go +++ b/cipher.go @@ -2,8 +2,6 @@ package openssl -import "C" - import ( "crypto/cipher" "errors" diff --git a/cmd/checkheader/main.go b/cmd/checkheader/main.go index eda1d700..1fe1df72 100644 --- a/cmd/checkheader/main.go +++ b/cmd/checkheader/main.go @@ -28,7 +28,7 @@ import ( const description = ` Example: A check operation: - go run ./cmd/checkheader --ossl-include /usr/local/src/openssl-1.1.1/include -shim ./internal/ossl/shims.h + go run ./cmd/checkheader --ossl-include /usr/local/src/openssl-1.1.1/include -shim ./internal/ossl/shims.h Checkheader generates a C program and compiles it with gcc. The compilation verifies types and functions defined in the target header file match the definitions in --ossl-include. ` @@ -119,15 +119,17 @@ func generate(header string) (string, error) { } for _, enum := range src.Enums { - if enum.Name == "_EVP_PKEY_OP_DERIVE" { - // This is defined differently in OpenSSL 3, - // but in our code it is only used in OpenSSL 1. - continue + for _, enumValue := range enum.Values { + if enumValue.Name == "_EVP_PKEY_OP_DERIVE" { + // This is defined differently in OpenSSL 3, + // but in our code it is only used in OpenSSL 1. + continue + } + name := strings.TrimPrefix(enumValue.Name, "_") + fmt.Fprintf(w, "#ifdef %s\n", name) + fmt.Fprintf(w, "_Static_assert(%s == %s, \"%s\");\n", enumValue.Value, name, enumValue.Name) + fmt.Fprintln(w, "#endif") } - name := strings.TrimPrefix(enum.Name, "_") - fmt.Fprintf(w, "#ifdef %s\n", name) - fmt.Fprintf(w, "_Static_assert(%s == %s, \"%s\");\n", enum.Value, name, enum.Name) - fmt.Fprintln(w, "#endif") } for _, def := range src.TypeDefs { diff --git a/cmd/genaesmodes/main.go b/cmd/genaesmodes/main.go index 22a89417..f202a443 100644 --- a/cmd/genaesmodes/main.go +++ b/cmd/genaesmodes/main.go @@ -39,7 +39,7 @@ func main() { if gopackage := os.Getenv("GOPACKAGE"); gopackage != "" { pkg = gopackage } - fmt.Fprint(&b, "//go:build cgo && !cmd_go_bootstrap\n\n") + fmt.Fprint(&b, "//go:build !cmd_go_bootstrap\n\n") fmt.Fprintf(&b, "package %s\n\n", pkg) fmt.Fprint(&b, `import "crypto/cipher"`+"\n\n") diff --git a/cmd/mkcgo/generate.go b/cmd/mkcgo/generate.go index 14b77ec3..9181e4e1 100644 --- a/cmd/mkcgo/generate.go +++ b/cmd/mkcgo/generate.go @@ -2,26 +2,31 @@ package main import ( "fmt" + "go/token" "io" "slices" "strconv" "strings" - "unicode" - "unicode/utf8" "github.com/golang-fips/openssl/v2/internal/mkcgo" ) +func printHeader(w io.Writer) { + fmt.Fprintf(w, "// Code generated by mkcgo. DO NOT EDIT.\n\n") +} + // generateGo output Go source file from src. func generateGo(src *mkcgo.Source, w io.Writer) { // Output header notice and package declaration. - fmt.Fprintf(w, "// Code generated by mkcgo. DO NOT EDIT.\n\n") + printHeader(w) fmt.Fprintf(w, "package %s\n\n", *packageName) // This block outputs C header includes and forward declarations for loader functions. fmt.Fprintf(w, "/*\n") fmt.Fprintf(w, "#cgo CFLAGS: -Wno-attributes\n") - fmt.Fprintf(w, "#cgo unix LDFLAGS: -ldl\n\n") + if dynload() { + fmt.Fprintf(w, "#cgo unix LDFLAGS: -ldl\n\n") + } if *includeHeader != "" { fmt.Fprintf(w, "#include \"%s\"\n", *includeHeader) } @@ -30,20 +35,25 @@ func generateGo(src *mkcgo.Source, w io.Writer) { fmt.Fprintf(w, "import \"C\"\n") fmt.Fprintf(w, "import \"unsafe\"\n\n") + // Generate Externs for C extern variables. + generateGoExterns(src.Externs, w) + // Generate Go enum values for C enums. generateGoEnums(src.Enums, w) // Generate type aliases for all - generateGoAliases(src.Funcs, w) + generateGoAliases(src.Funcs, src.Externs, src.Enums, w) - // Generate Go wrapper functions that load and unload the C symbols. - for _, tag := range src.Tags() { - fmt.Fprintf(w, "func %s_%s(handle unsafe.Pointer) {\n", goSymName("mkcgoLoad"), tag) - fmt.Fprintf(w, "\tC.__mkcgo_load_%s(handle)\n", tag) - fmt.Fprintf(w, "}\n\n") - fmt.Fprintf(w, "func %s_%s() {\n", goSymName("mkcgoUnload"), tag) - fmt.Fprintf(w, "\tC.__mkcgo_unload_%s()\n", tag) - fmt.Fprintf(w, "}\n\n") + if dynload() { + // Generate Go wrapper functions that load and unload the C symbols. + for _, tag := range src.Tags() { + fmt.Fprintf(w, "func %s_%s(handle unsafe.Pointer) {\n", goSymName("mkcgoLoad"), tag) + fmt.Fprintf(w, "\tC.__mkcgo_load_%s(handle)\n", tag) + fmt.Fprintf(w, "}\n\n") + fmt.Fprintf(w, "func %s_%s() {\n", goSymName("mkcgoUnload"), tag) + fmt.Fprintf(w, "\tC.__mkcgo_unload_%s()\n", tag) + fmt.Fprintf(w, "}\n\n") + } } // Generate error wrapper noescape function, which hides the @@ -73,7 +83,7 @@ func generateGo(src *mkcgo.Source, w io.Writer) { // generateGo124 generates Go source code Go 1.24 and later. func generateGo124(src *mkcgo.Source, w io.Writer) { // Output header notice and package declaration. - fmt.Fprintf(w, "// Code generated by mkcgo. DO NOT EDIT.\n\n") + printHeader(w) fmt.Fprintf(w, "//go:build go1.24 && !cmd_go_bootstrap\n\n") fmt.Fprintf(w, "package %s\n\n", *packageName) @@ -92,34 +102,45 @@ func generateGo124(src *mkcgo.Source, w io.Writer) { fmt.Fprintf(w, "import \"C\"\n") } -// generateGoEnums generates Go enum values for C enums. -func generateGoEnums(enums []*mkcgo.Enum, w io.Writer) { - if len(enums) == 0 { +// generateGoExterns generates Go variables for C extern variables. +func generateGoExterns(externs []*mkcgo.Extern, w io.Writer) { + if len(externs) == 0 { return } - fmt.Fprintf(w, "const (\n") - for _, enum := range enums { - fmt.Fprintf(w, "\t%s = %s\n", goSymName(enum.Name), enum.Value) + fmt.Fprintf(w, "var (\n") + for _, extern := range externs { + fmt.Fprintf(w, "\t%s = C.%s\n", goSymName(extern.Name), extern.Name) } fmt.Fprintf(w, ")\n\n") } +// generateGoEnums generates Go enum values for C enums. +func generateGoEnums(enums []*mkcgo.Enum, w io.Writer) { + for _, enum := range enums { + fmt.Fprintf(w, "const (\n") + for _, enumValue := range enum.Values { + fmt.Fprintf(w, "\t%s %s = %s\n", goSymName(enumValue.Name), enum.Type, enumValue.Value) + } + fmt.Fprintf(w, ")\n\n") + } +} + // generateGoAliases generates Go type aliases for C types. -func generateGoAliases(funcs []*mkcgo.Func, w io.Writer) { +func generateGoAliases(funcs []*mkcgo.Func, externs []*mkcgo.Extern, enums []*mkcgo.Enum, w io.Writer) { // Traverse all functions and collect the unique C types. ctypes := make(map[string]struct{}) - for _, fn := range funcs { - handleType := func(typ string) { - if typ == "" { - return - } - typ = strings.TrimPrefix(typ, "const ") - typ = strings.TrimRight(typ, "*") - if _, ok := ctypes[typ]; ok { - return - } - ctypes[typ] = struct{}{} + handleType := func(typ string) { + if typ == "" { + return + } + typ = strings.TrimPrefix(typ, "const ") + typ = strings.TrimRight(typ, "*") + if _, ok := ctypes[typ]; ok { + return } + ctypes[typ] = struct{}{} + } + for _, fn := range funcs { for _, p := range fn.Params { if p.Variadic() { continue @@ -128,6 +149,12 @@ func generateGoAliases(funcs []*mkcgo.Func, w io.Writer) { } handleType(fn.Ret) } + for _, extern := range externs { + handleType(extern.Type) + } + for _, enum := range enums { + handleType(enum.Type) + } types := make([]string, 0, len(ctypes)) for typ := range ctypes { types = append(types, typ) @@ -146,7 +173,7 @@ func generateGoAliases(funcs []*mkcgo.Func, w io.Writer) { // the C functions defined in the autogenerated C source file. func generateCHeader(src *mkcgo.Source, w io.Writer) { // Header and includes. - fmt.Fprintf(w, "// Code generated by mkcgo. DO NOT EDIT.\n\n") + printHeader(w) fmt.Fprintf(w, "#ifndef MKCGO_H // only include this header once\n") fmt.Fprintf(w, "#define MKCGO_H\n\n") @@ -166,11 +193,27 @@ func generateCHeader(src *mkcgo.Source, w io.Writer) { fmt.Fprintf(w, "typedef %s %s;\n", def.Type, def.Name) } fmt.Fprintf(w, "\n") - fmt.Fprintf(w, "enum {\n") + if len(src.Externs) > 0 { + for _, def := range src.Externs { + fmt.Fprintf(w, "extern %s %s;\n", def.Type, def.Name) + } + fmt.Fprintf(w, "\n") + } for _, enum := range src.Enums { - fmt.Fprintf(w, "\t%s = %s,\n", enum.Name, enum.Value) + if enum.Type != "" { + fmt.Fprintf(w, "typedef ") + } + fmt.Fprintf(w, "enum {\n") + for _, enumValue := range enum.Values { + fmt.Fprintf(w, "\t%s = %s,\n", enumValue.Name, enumValue.Value) + } + if enum.Type != "" { + fmt.Fprintf(w, "} %s;", enum.Type) + } else { + fmt.Fprintf(w, "};") + } + fmt.Fprintf(w, "\n\n") } - fmt.Fprintf(w, "};\n\n") // Custom types fmt.Fprintf(w, "typedef void* %s;\n", mkcgoErrState) @@ -178,12 +221,14 @@ func generateCHeader(src *mkcgo.Source, w io.Writer) { fmt.Fprintf(w, "void mkcgo_err_free(%s);\n", mkcgoErrState) fmt.Fprintf(w, "void mkcgo_err_clear();\n\n") - // Add forward declarations for loader functions. - for _, tag := range src.Tags() { - fmt.Fprintf(w, "void __mkcgo_load_%s(void* handle);\n", tag) - fmt.Fprintf(w, "void __mkcgo_unload_%s();\n", tag) + if dynload() { + // Add forward declarations for loader functions. + for _, tag := range src.Tags() { + fmt.Fprintf(w, "void __mkcgo_load_%s(void* handle);\n", tag) + fmt.Fprintf(w, "void __mkcgo_unload_%s();\n", tag) + } + fmt.Fprintf(w, "\n") } - fmt.Fprintf(w, "\n") // Add forward declarations for optional functions. for _, fn := range src.Funcs { @@ -212,7 +257,7 @@ func generateCHeader(src *mkcgo.Source, w io.Writer) { // generateC creates the C source file content. func generateC(src *mkcgo.Source, w io.Writer) { // Header and includes. - fmt.Fprintf(w, "// Code generated by mkcgo. DO NOT EDIT.\n\n") + printHeader(w) fmt.Fprintf(w, "#include \n") fmt.Fprintf(w, "#include \n") @@ -224,76 +269,40 @@ func generateC(src *mkcgo.Source, w io.Writer) { fmt.Fprintf(w, "#include \"%s\"\n", autogeneratedFileName(".h")) fmt.Fprintf(w, "\n") - // Platform-specific includes. - fmt.Fprintf(w, "#ifdef _WIN32\n") - fmt.Fprintf(w, "#include \n") - fmt.Fprintf(w, "#define dlsym GetProcAddress\n") - fmt.Fprintf(w, "#else\n") - fmt.Fprintf(w, "#include \n") - fmt.Fprintf(w, "#endif\n\n") + if dynload() { + // Platform-specific includes. + fmt.Fprintf(w, "#ifdef _WIN32\n") + fmt.Fprintf(w, "#include \n") + fmt.Fprintf(w, "#define dlsym GetProcAddress\n") + fmt.Fprintf(w, "#else\n") + fmt.Fprintf(w, "#include \n") + fmt.Fprintf(w, "#endif\n\n") + } // Function pointer declarations. for _, fn := range src.Funcs { if fn.VariadicTarget != "" { continue } - fmt.Fprintf(w, "%s (*_g_%s)(%s);\n", fn.Ret, fn.ImportName(), fnToCArgs(fn, true, false)) + if dynload() { + fmt.Fprintf(w, "%s (*_g_%s)(%s);\n", fn.Ret, fn.ImportName(), fnToCArgs(fn, true, false)) + } else { + fmt.Fprintf(w, "%s %s(%s);\n", fn.Ret, fn.ImportName(), fnToCArgs(fn, true, false)) + } } fmt.Fprintf(w, "\n") + if dynload() { + fmt.Fprintf(w, "#define __mkcgo__dlsym_nocheck(varname, funcname) _g_##varname = (typeof(_g_##varname))dlsym(handle, #funcname);\n\n") + fmt.Fprintf(w, "#define __mkcgo__dlsym(name) __mkcgo__dlsym2(name, name)\n\n") + fmt.Fprintf(w, "#define __mkcgo__dlsym2(varname, funcname) \\\n") + fmt.Fprintf(w, "\t__mkcgo__dlsym_nocheck(varname, funcname) \\\n") + fmt.Fprintf(w, "\tif (_g_##varname == NULL) { \\\n") + fmt.Fprintf(w, "\t\tfprintf(stderr, \"Cannot get required symbol \" #funcname \"\\n\"); \\\n") + fmt.Fprintf(w, "\t\tabort(); \\\n") + fmt.Fprintf(w, "\t}\n\n") - fmt.Fprintf(w, "#define __mkcgo__dlsym_nocheck(varname, funcname) _g_##varname = (typeof(_g_##varname))dlsym(handle, #funcname);\n\n") - fmt.Fprintf(w, "#define __mkcgo__dlsym(name) __mkcgo__dlsym2(name, name)\n\n") - fmt.Fprintf(w, "#define __mkcgo__dlsym2(varname, funcname) \\\n") - fmt.Fprintf(w, "\t__mkcgo__dlsym_nocheck(varname, funcname) \\\n") - fmt.Fprintf(w, "\tif (_g_##varname == NULL) { \\\n") - fmt.Fprintf(w, "\t\tfprintf(stderr, \"Cannot get required symbol \" #funcname \"\\n\"); \\\n") - fmt.Fprintf(w, "\t\tabort(); \\\n") - fmt.Fprintf(w, "\t}\n\n") - - // Loader and unloader functions for each tag. - for _, tag := range src.Tags() { - fmt.Fprintf(w, "void __mkcgo_load_%s(void* handle) {\n", tag) - for _, fn := range src.Funcs { - if fn.VariadicTarget != "" { - continue - } - tags := fn.Tags - if len(tags) == 0 { - tags = []mkcgo.TagAttr{{}} - } - for _, tagAttr := range tags { - if tagAttr.Tag == tag { - if tagAttr.Name != "" { - // TODO: if necessary, support optional functions in here too. - fmt.Fprintf(w, "\t__mkcgo__dlsym2(%s, %s)\n", fn.ImportName(), tagAttr.Name) - } else if fn.Optional { - fmt.Fprintf(w, "\t__mkcgo__dlsym_nocheck(%s, %s)\n", fn.ImportName(), fn.ImportName()) - } else { - fmt.Fprintf(w, "\t__mkcgo__dlsym(%s)\n", fn.ImportName()) - } - break - } - } - } - fmt.Fprintf(w, "}\n\n") - - fmt.Fprintf(w, "void __mkcgo_unload_%s() {\n", tag) - for _, fn := range src.Funcs { - if fn.VariadicTarget != "" { - continue - } - tags := fn.Tags - if len(tags) == 0 { - tags = []mkcgo.TagAttr{{}} - } - for _, tagAttr := range tags { - if tagAttr.Tag == tag { - fmt.Fprintf(w, "\t_g_%s = NULL;\n", fn.ImportName()) - break - } - } - } - fmt.Fprintf(w, "}\n\n") + // Loader and unloader functions for each tag. + generateMkcgoLoadFunctions(src, w) } // Generate C function wrappers. @@ -330,7 +339,7 @@ func generateGoFn(fn *mkcgo.Func, w io.Writer) { return } goType, needCast := cTypeToGo(fn.Ret, false) - if fn.NoError { + if fn.NoError || *noerrors { fmt.Fprintf(w, " %s ", goType) } else { fmt.Fprintf(w, " (%s, error) ", goType) @@ -343,7 +352,7 @@ func generateGoFn(fn *mkcgo.Func, w io.Writer) { goType = fmt.Sprintf("(%s)(unsafe.Pointer", goType) needUnsafeCast = true } - if fn.NoError { + if fn.NoError || *noerrors { // No error handling, just cast the return value if necessary. fmt.Fprintf(w, "\treturn ") if needCast { @@ -381,19 +390,23 @@ func generateGoFn(fn *mkcgo.Func, w io.Writer) { } func generateCFn(typedefs map[string]string, fn *mkcgo.Func, w io.Writer) { + var prefix string + if dynload() { + prefix = "_g_" + } if !fnNeedErrWrapper(fn) { fmt.Fprintf(w, "%s %s(%s) {\n\t", fn.Ret, fnCName(fn), fnToCArgs(fn, true, true)) if !isVoid(fn.Ret) { fmt.Fprintf(w, "return ") } - fmt.Fprintf(w, "_g_%s(%s);\n", fn.ImportName(), fnToCArgs(fn, false, true)) + fmt.Fprintf(w, "%s%s(%s);\n", prefix, fn.ImportName(), fnToCArgs(fn, false, true)) fmt.Fprintf(w, "}\n\n") return } fmt.Fprintf(w, "%s %s(%s) {\n", fn.Ret, fnCName(fn), fnCErrWrapperParams(fn, true)) fmt.Fprintf(w, "\tmkcgo_err_clear();\n") // clear any previous error - fmt.Fprintf(w, "\t%s _ret = _g_%s(%s);\n", fn.Ret, fn.ImportName(), fnToCArgs(fn, false, true)) + fmt.Fprintf(w, "\t%s _ret = %s%s(%s);\n", fn.Ret, prefix, fn.ImportName(), fnToCArgs(fn, false, true)) errCond := "<= 0" if fn.ErrCond != "" { errCond = fn.ErrCond @@ -437,6 +450,7 @@ func isStdType(t string) bool { // cstdTypesToGo maps C standard types to Go types. var cstdTypesToGo = map[string]string{ + "bool": "bool", "int8_t": "int8", "uint8_t": "uint8", "int16_t": "int16", @@ -445,10 +459,11 @@ var cstdTypesToGo = map[string]string{ "uint32_t": "uint32", "int64_t": "int64", "uint64_t": "uint64", + "short": "int16", + "unsigned short": "uint16", "int": "int32", + "unsigned": "uint32", "unsigned int": "uint32", - "long": "int32", - "unsigned long": "uint32", "long long": "int64", "unsigned long long": "uint64", "size_t": "int", @@ -457,12 +472,18 @@ var cstdTypesToGo = map[string]string{ "unsigned char": "byte", "signed char": "int8", "void": "", + // On Windows, long and unsigned long are 32 bits, but on Unix they are 64 bits. + // We assume the Unix variant here, as it won't cause information loss when compiling + // for Windows. + "long": "int64", + "unsigned long": "uint64", } // cstdTypesToCgo maps C standard types to special cgo types. // Most C don't need any special handling, only the ones that have spaces. var cstdTypesToCgo = map[string]string{ "signed char": "schar", + "unsigned": "uint", "unsigned char": "uchar", "unsigned short": "ushort", "unsigned int": "uint", @@ -482,7 +503,8 @@ func cTypeToGo(t string, cgo bool) (string, bool) { return "", true } if strings.HasPrefix(t, "void*") { - return "unsafe.Pointer", false + n := strings.Count(t, "*") + return strings.Repeat("*", n-1) + "unsafe.Pointer", false } if strings.HasSuffix(t, "*") { // Remove all trailing '*' characters. @@ -614,7 +636,7 @@ func fnCNameAvailable(fn *mkcgo.Func) string { // fnNeedErrWrapper reports whether function fn needs an error wrapper. func fnNeedErrWrapper(fn *mkcgo.Func) bool { - return !fn.NoError && !isVoid(fn.Ret) + return !*noerrors && !fn.NoError && !isVoid(fn.Ret) } // fnCalledFromGo reports whether function fn is called from Go code. @@ -629,8 +651,10 @@ func goSymName(name string) string { if name == "" { panic("empty name") } - ch, _ := utf8.DecodeRuneInString(name) - isPrivate := !unicode.IsUpper(ch) + // Strip the 'go_' prefix commonly used in shims so Go symbols are nicer. + name = strings.TrimPrefix(name, "go_") + + isPrivate := !token.IsExported(name) if *private == isPrivate { // Same access level, no need to change. return name @@ -649,3 +673,643 @@ func goSymName(name string) string { // Uppercase the first letter. return strings.ToUpper(name[:1]) + name[1:] } + +// getFrameworkPath returns the absolute framework path. +func getFrameworkPath(dylib mkcgo.Framework) string { + if dylib.Name == "" && dylib.Version == "" { + return "" + } + return fmt.Sprintf("/System/Library/Frameworks/%s.framework/Versions/%s/%s", dylib.Name, dylib.Version, dylib.Name) +} + +// needsAssembly checks if assembly trampolines are needed for nocgo mode. +func needsAssembly() bool { + return dynamic() +} + +// generateNocgoGo generates Go source file for nocgo mode from src. +func generateNocgoGo(src *mkcgo.Source, w io.Writer) { + // Output header notice and package declaration. + printHeader(w) + + tags := "!cgo" + if *extratags != "" { + tags += " && (" + *extratags + ")" + } + fmt.Fprintf(w, "//go:build %s\n\n", tags) + + fmt.Fprintf(w, "package %s\n\n", *packageName) + + // Import necessary packages for nocgo mode + fmt.Fprintf(w, "import (\n") + fmt.Fprintf(w, "\t\"runtime\"\n") + fmt.Fprintf(w, "\t\"unsafe\"\n") + fmt.Fprintf(w, ")\n\n") + + // Generate cgo_import_dynamic directives for extern variables + for _, ext := range src.Externs { + extName := ext.Name + if ext.Static { + localName := extName + if !strings.HasPrefix(extName, "go_") { + localName = "go_" + extName + } + fmt.Fprintf(w, "//go:linkname %s %s\n", localName, localName) + continue + } + frameworkPath := getFrameworkPath(ext.Framework) + fmt.Fprintf(w, "//go:cgo_import_dynamic _mkcgo_%s %s \"%s\"\n", extName, extName, frameworkPath) + fmt.Fprintf(w, "//go:linkname _mkcgo_%s _mkcgo_%s\n", extName, extName) + } + fmt.Fprintf(w, "\n") + + // Generate cgo_import_dynamic directives for each function + for _, fn := range src.Funcs { + // Skip base variadic functions unless they are targets for wrapper functions + // Variadic wrapper functions don't need their own imports since they call the variadic target + if fn.Attrs.VariadicTarget != "" { + continue + } + if fn.Static { + localName := fn.Name + if !strings.HasPrefix(localName, "go_") { + localName = "go_" + localName + } + fmt.Fprintf(w, "//go:linkname %s %s\n", localName, localName) + } else { + if dynamic() { + fmt.Fprintf(w, "//go:cgo_import_dynamic _mkcgo_%s %s \"%s\"\n", fn.Name, fn.Name, getFrameworkPath(fn.Framework)) + } + } + } + fmt.Fprintf(w, "\n") + + // For functions that were statically imported, declare a byte variable + // and pointer matching the local import name (e.g., "go_MD5"). This is needed so + // the generated nocgo code can reference the symbol address when using + // static imports. + for _, fn := range src.Funcs { + if !fnCalledFromGo(fn) { + continue + } + if !fn.Static { + continue + } + localName := fn.Name + if !strings.HasPrefix(localName, "go_") { + localName = "go_" + localName + } + // Use byte + pointer pattern for all functions + fmt.Fprintf(w, "var %s byte\n", localName) + } + fmt.Fprintf(w, "\n") + + // Generate all type aliases + generateNocgoAliases(src.TypeDefs, w) + + // Generate enums + generateNocgoEnums(src.Enums, w) + + // Generate extern variables + generateNocgoExterns(src.Externs, w) + + // Generate trampoline address variables and wrapper functions + typePtrs := make(map[string]bool, len(src.TypeDefs)) + for _, def := range src.TypeDefs { + if !strings.ContainsRune(def.Type, '*') { + continue + } + typ, _ := cTypeToGo(def.Name, false) + typePtrs[typ] = true + } + for _, fn := range src.Funcs { + generateNocgoFn(typePtrs, src, fn, w) + } + + // Generate MkcgoLoad and MkcgoUnload functions for each tag + generateMkcgoLoadFunctions(src, w) +} + +// generateNocgoAliases generates Go type aliases for nocgo mode. +func generateNocgoAliases(typedefs []*mkcgo.TypeDef, w io.Writer) { + seenTypes := make(map[string]bool) + + // Handle typedefs first, as they can create proper type aliases + for _, typedef := range typedefs { + // For basic types, make it an alias to the appropriate Go type + goType, _ := cTypeToGo(typedef.Type, false) + name := goSymName(typedef.Name) + if goType != "" && goType != "unsafe.Pointer" { + fmt.Fprintf(w, "type %s = %s\n", name, goType) + seenTypes[name] = true + } else { + fmt.Fprintf(w, "type %s unsafe.Pointer\n", name) + seenTypes[name] = true + } + } + + fmt.Fprintf(w, "\n") +} + +// generateNocgoEnums generates Go enum values for nocgo mode. +func generateNocgoEnums(enums []*mkcgo.Enum, w io.Writer) { + for _, enum := range enums { + if enum.Type != "" { + // Generate the type alias + fmt.Fprintf(w, "type %s int32\n\n", enum.Type) + } + + fmt.Fprintf(w, "const (\n") + for _, enumValue := range enum.Values { + if enum.Type != "" { + fmt.Fprintf(w, "\t%s %s = %s\n", goSymName(enumValue.Name), enum.Type, enumValue.Value) + } else { + fmt.Fprintf(w, "\t%s = %s\n", goSymName(enumValue.Name), enumValue.Value) + } + } + fmt.Fprintf(w, ")\n\n") + } +} + +// generateNocgoExterns generates Go extern variables for nocgo mode. +func generateNocgoExterns(externs []*mkcgo.Extern, w io.Writer) { + if len(externs) == 0 { + return + } + + // First, generate pointer variables for extern symbols + fmt.Fprintf(w, "var (\n") + for _, ext := range externs { + goType, _ := cTypeToGo(ext.Type, false) + fmt.Fprintf(w, "\t_mkcgo_%s %s\n", ext.Name, goType) + } + fmt.Fprintf(w, ")\n\n") + + for _, ext := range externs { + goType, _ := cTypeToGo(ext.Type, false) + fmt.Fprintf(w, "//go:noinline\n") + fmt.Fprintf(w, "func _mkcgo_addr_%s() *%s { return &_mkcgo_%s }\n", ext.Name, goType, ext.Name) + } + + // Then, generate the actual variables that dereference the pointers + fmt.Fprintf(w, "var (\n") + for _, ext := range externs { + // Convert extern names to Go variable names + goName := goSymName(ext.Name) + goType, _ := cTypeToGo(ext.Type, false) + fmt.Fprintf(w, "\t%s %s = *_mkcgo_addr_%s()\n", goName, goType, ext.Name) + } + fmt.Fprintf(w, ")\n\n") +} + +func trampolineName(fn *mkcgo.Func) string { + if fn.Static { + name := fn.Name + if !strings.HasPrefix(name, "go_") { + name = "go_" + name + } + return name + } + if dynload() { + return fmt.Sprintf("_mkcgo_%s", fn.ImportName()) + } + return fmt.Sprintf("_mkcgo_%s_trampoline_addr", fn.ImportName()) +} + +// generateNocgoFn generates Go function wrapper for nocgo mode. +func generateNocgoFn(typePtrs map[string]bool, src *mkcgo.Source, fn *mkcgo.Func, w io.Writer) { + if fn.Variadic() { + if !fn.Static { + fmt.Fprintf(w, "var %s uintptr\n\n", trampolineName(fn)) + } + // Nothing else to do. + return + } + if fn.Optional { + // Generate a function that returns true if the function is available. + // For nocgo mode, check if the function pointer is loaded. + fmt.Fprintf(w, "func %s() bool {\n", fnGoNameAvailable(fn)) + fmt.Fprintf(w, "\treturn %s != 0\n", fnCName(fn)) + fmt.Fprintf(w, "}\n\n") + } + + // Generate trampoline address variable + if fn.VariadicTarget == "" && !fn.Static { + fmt.Fprintf(w, "var %s uintptr\n\n", trampolineName(fn)) + } + + // Generate Go wrapper function + fmt.Fprintf(w, "func %s(", goSymName(fn.Name)) + + // Generate parameters + paramCount := 0 + for i, param := range fn.Params { + // Skip void parameters + if param.Type == "void" { + continue + } + + if paramCount > 0 { + fmt.Fprintf(w, ", ") + } + + // Convert C types to Go types for nocgo mode + goType, _ := cTypeToGo(param.Type, false) + paramName := param.Name + if paramName == "" { + paramName = fmt.Sprintf("arg%d", i) + } + fmt.Fprintf(w, "%s %s", paramName, goType) + paramCount++ + } + fmt.Fprintf(w, ")") + + // Generate return type - only include error for functions that need error wrappers + if fn.Ret != "" && fn.Ret != "void" { + goRetType, _ := cTypeToGo(fn.Ret, false) + if fnNeedErrWrapper(fn) { + fmt.Fprintf(w, " (%s, error)", goRetType) + } else { + fmt.Fprintf(w, " %s", goRetType) + } + } else if fnNeedErrWrapper(fn) { + fmt.Fprintf(w, " error") + } + + fmt.Fprintf(w, " {\n") + + // Special handling for MacOS ARM64 stack params + // Generate architecture-specific code + var tmp strings.Builder + needsSpecialHandling := macosDarwinArm64Params(src, fn, &tmp) + + if needsSpecialHandling { + fmt.Fprintf(w, "\tvar r0 uintptr\n") + fmt.Fprintf(w, "\tif runtime.GOOS == \"darwin\" && runtime.GOARCH == \"arm64\" {\n") + fmt.Fprintf(w, "\t\t") + if fn.Ret != "" && fn.Ret != "void" { + fmt.Fprintf(w, "r0, _, _ = ") + } + + // Use static function pointer or trampoline address + functionRef := trampolineName(fn) + if fn.Static { + functionRef = fmt.Sprintf("uintptr(unsafe.Pointer(&%s))", functionRef) + } + + fmt.Fprintf(w, "syscallN(%s, %s)\n", functionRef, tmp.String()) + fmt.Fprintf(w, "\t} else {\n") + } + generateNocgoFnBody(src, fn, !needsSpecialHandling, w) + if needsSpecialHandling { + fmt.Fprintf(w, "\t}\n") + } + + for _, param := range fn.Params { + // Skip void parameters + if param.Type == "void" { + continue + } + + // Convert C types to Go types for nocgo mode + goType, _ := cTypeToGo(param.Type, false) + _, isPtr := typePtrs[goType] + if isPtr || strings.HasPrefix(goType, "*") { + fmt.Fprintf(w, "\truntime.KeepAlive(%s)\n", param.Name) + } + } + + // Generate return statement - only include error for functions that need error wrappers + if fn.Ret != "" && fn.Ret != "void" { + goRetType, _ := cTypeToGo(fn.Ret, false) + if fnNeedErrWrapper(fn) { + errCond := "<= 0" + zeroVal := "0" + if fn.ErrCond != "" { + errCond = fn.ErrCond + } else if strings.Contains(fn.Ret, "*") { + errCond = "== nil" + zeroVal = "nil" + } else if _, ok := typePtrs[goRetType]; ok { + errCond = "== nil" + zeroVal = "nil" + } + fmt.Fprintf(w, "\tif %s(r0) %s {\n", goRetType, errCond) + fmt.Fprintf(w, "\t\treturn %s, newMkcgoErr(\"%s\", nil)\n", zeroVal, fn.Name) + fmt.Fprintf(w, "\t}\n") + if strings.HasPrefix(goRetType, "*") { + // Pointer return types need to go through unsafe.Pointer + fmt.Fprintf(w, "\treturn (%s)(unsafe.Pointer(r0)), nil\n", goRetType) + } else { + fmt.Fprintf(w, "\treturn %s(r0), nil\n", goRetType) + } + } else { + if strings.HasPrefix(goRetType, "*") { + // Pointer return types need to go through unsafe.Pointer + fmt.Fprintf(w, "\treturn (%s)(unsafe.Pointer(r0))\n", goRetType) + } else { + fmt.Fprintf(w, "\treturn %s(r0)\n", goRetType) + } + } + } else if fnNeedErrWrapper(fn) { + fmt.Fprintf(w, "\treturn nil\n") + } + + fmt.Fprintf(w, "}\n\n") +} + +// generateNocgoFnBody generates Go function wrapper body for nocgo mode. +func generateNocgoFnBody(src *mkcgo.Source, fn *mkcgo.Func, newR0 bool, w io.Writer) { + fnArg := trampolineName(fn) + if fn.Static { + fnArg = fmt.Sprintf("uintptr(unsafe.Pointer(&%s))", fnArg) + } + + // Generate the syscall invocation with proper argument handling + if fn.Ret != "" && fn.Ret != "void" { + colon := ":" + if !newR0 { + colon = "" + } + fmt.Fprintf(w, "\tr0, _, _ %s= syscallN(%s", colon, fnArg) + } else { + fmt.Fprintf(w, "\tsyscallN(%s", fnArg) + } + + // Add actual parameters + for i, param := range fn.Params { + // Skip void parameters + if param.Type == "void" { + continue + } + + paramName := param.Name + if paramName == "" { + paramName = fmt.Sprintf("arg%d", i) + } + + // Convert parameter to uintptr, handling different types correctly + goType, _ := cTypeToGo(param.Type, false) + if strings.HasPrefix(goType, "*") { + // Pointer types need to go through unsafe.Pointer + fmt.Fprintf(w, ", uintptr(unsafe.Pointer(%s))", paramName) + } else { + fmt.Fprintf(w, ", uintptr(%s)", paramName) + } + } + fmt.Fprintf(w, ")\n") +} + +// generateAssembly generates the assembly trampoline file for nocgo mode. +// This function is only called when dynamic imports are used. +func generateAssembly(src *mkcgo.Source, w io.Writer) { + printHeader(w) + tags := "!cgo" + if *extratags != "" { + tags += " && (" + *extratags + ")" + } + fmt.Fprintf(w, "//go:build %s\n\n", tags) + fmt.Fprintf(w, "#include \"textflag.h\"\n\n") + + fmt.Fprintf(w, ` +#ifndef GOARCH_amd64 +#ifndef GOARCH_arm64 +#ifndef GOARCH_riscv64 +#ifndef GOARCH_loong64 +#ifndef GOARCH_mips64 +#ifndef GOARCH_mips64le +#ifndef GOARCH_ppc64 +#ifndef GOARCH_ppc64le +#ifndef GOARCH_sparc64 +#define _GOPTRSIZE 4 +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif + + +#ifndef _GOPTRSIZE +#define _GOPTRSIZE 8 +#endif +`) + + // Generate trampolines for each function + for _, fn := range src.Funcs { + fnName := fn.Name + fmt.Fprintf(w, "TEXT _mkcgo_%s_trampoline<>(SB),NOSPLIT,$0-0\n", fnName) + fmt.Fprintf(w, " JMP _mkcgo_%s(SB)\n", fnName) + fmt.Fprintf(w, "GLOBL ·_mkcgo_%s_trampoline_addr(SB), RODATA, $_GOPTRSIZE\n", fnName) + fmt.Fprintf(w, "DATA ·_mkcgo_%s_trampoline_addr(SB)/_GOPTRSIZE, $_mkcgo_%s_trampoline<>(SB)\n\n", fnName, fnName) + } +} + +// macosDarwinArm64Params writes the string representing the parameters +// passed to a function on macOS ARM64. This platform is special +// because the first 9 parameters are passed in registers, and +// the rest are passed on the stack layed out using each type +// natural alignment. Also, variadic parameters are passed on the stack. +func macosDarwinArm64Params(src *mkcgo.Source, fn *mkcgo.Func, w io.Writer) bool { + nonVariadicArgs := len(fn.Params) + if fn.VariadicTarget != "" { + var target *mkcgo.Func + for _, f := range src.Funcs { + if f.Name == fn.VariadicTarget { + target = f + break + } + } + if target == nil { + panic(fmt.Errorf("variadic target %q for %q not found: ", fn.VariadicTarget, fn.Name)) + } + nonVariadicArgs = len(target.Params) + for i := len(target.Params) - 1; i >= 0; i-- { + if !target.Params[i].Variadic() { + break + } + nonVariadicArgs-- + } + } + var stackOffset, lastShift int + shift := func(size int) { + v := lastShift + size + if v%size != 0 { + // Requires padding + pad := v % size + v += pad + stackOffset += pad + } + stackOffset += size + if v < 8 { + lastShift = v + fmt.Fprintf(w, "<<%d", 64-v*8) + } else { + lastShift = 0 + } + } + var needSpecialHandling bool + for i, param := range fn.Params { + const maxParamsInRegisters = 8 + if i == nonVariadicArgs { + // Variadic parameters start here, so we need to pad + // the remaining registers with zeros. + for j := i + 1; j <= maxParamsInRegisters; j++ { + needSpecialHandling = true + if j != 0 { + fmt.Fprintf(w, ", ") + } + fmt.Fprintf(w, "0") + } + } + var goParam string + if goType, _ := cTypeToGo(param.Type, false); strings.HasPrefix(goType, "*") { + goParam = fmt.Sprintf("uintptr(unsafe.Pointer(%s))", param.Name) + } else { + goParam = fmt.Sprintf("uintptr(%s)", param.Name) + } + if i <= maxParamsInRegisters { + // Regular parameter handling for first 9 parameters. + if i != 0 { + fmt.Fprintf(w, ", ") + } + fmt.Fprint(w, goParam) + continue + } + paramSize := cTypeSize(src, param.Type) + if stackOffset%8 == 0 || stackOffset%8+paramSize > 8 { + fmt.Fprintf(w, ", ") + } else { + fmt.Fprintf(w, "|") + needSpecialHandling = true + } + fmt.Fprintf(w, "%s", goParam) + shift(paramSize) + } + return needSpecialHandling +} + +func cTypeSize(src *mkcgo.Source, name string) int { + if strings.Contains(name, "*") { + return 8 + } + name = strings.TrimPrefix(name, "const ") + var stdType string + if isStdType(name) { + stdType = name + } + if stdType == "" { + for _, def := range src.TypeDefs { + if def.Name == name { + stdType = def.Type + } + } + } + if stdType == "" { + for _, enum := range src.Enums { + if enum.Type == name { + stdType = "uint32_t" + } + } + } + switch stdType { + case "bool", "int8_t", "uint8_t", "char", "unsigned char", "signed char": + return 1 + case "int16_t", "uint16_t", "short", "unsigned short": + return 2 + case "int32_t", "uint32_t", "int", "unsigned int", "float": + return 4 + case "long", "long int", "unsigned long", "unsigned long int": + return 8 + default: + // Consider all other types as 8 bytes. + // We don't support types larger than 64 bits for now. + return 8 + } +} + +// generateMkcgoLoadFunctions generates MkcgoLoad and MkcgoUnload functions for each tag +func generateMkcgoLoadFunctions(src *mkcgo.Source, w io.Writer) { + if !dynload() { + // TODO: support tags for other modes too + return + } + // Get all tags from the source + + for _, tag := range src.Tags() { + var tagOpened bool + // Collect functions that should be loaded for this tag + for _, fn := range src.Funcs { + if fn.Attrs.VariadicTarget != "" { + // Skip variadic wrapper functions in nocgo mode as they don't have real symbols + continue + } + tags := fn.Tags + if len(tags) == 0 { + tags = []mkcgo.TagAttr{{}} + } + for _, tagAttr := range tags { + if tagAttr.Tag == tag { + if !tagOpened { + if *nocgo { + fmt.Fprintf(w, "func %s_%s(handle unsafe.Pointer) {\n", goSymName("mkcgoLoad"), tag) + } else { + fmt.Fprintf(w, "void __mkcgo_load_%s(void* handle) {\n", tag) + } + tagOpened = true + } + if *nocgo { + if tagAttr.Name != "" { + // TODO: if necessary, support optional functions in here too. + fmt.Fprintf(w, "\t_mkcgo_%s = dlsym(handle, \"%s\\x00\", %v)\n", fn.Name, tagAttr.Name, fn.Optional) + } else { + fmt.Fprintf(w, "\t_mkcgo_%s = dlsym(handle, \"%s\\x00\", %v)\n", fn.Name, fn.Name, fn.Optional) + } + } else { + if tagAttr.Name != "" { + // TODO: if necessary, support optional functions in here too. + fmt.Fprintf(w, "\t__mkcgo__dlsym2(%s, %s)\n", fn.ImportName(), tagAttr.Name) + } else if fn.Optional { + fmt.Fprintf(w, "\t__mkcgo__dlsym_nocheck(%s, %s)\n", fn.ImportName(), fn.ImportName()) + } else { + fmt.Fprintf(w, "\t__mkcgo__dlsym(%s)\n", fn.ImportName()) + } + } + break + } + } + } + if tagOpened { + fmt.Fprintf(w, "}\n\n") + if *nocgo { + fmt.Fprintf(w, "func %s_%s() {\n", goSymName("mkcgoUnload"), tag) + } else { + fmt.Fprintf(w, "void __mkcgo_unload_%s() {\n", tag) + } + for _, fn := range src.Funcs { + if fn.Attrs.VariadicTarget != "" { + // Skip variadic wrapper functions in nocgo mode as they don't have real symbols + continue + } + tags := fn.Tags + if len(tags) == 0 { + tags = []mkcgo.TagAttr{{}} + } + for _, tagAttr := range tags { + if tagAttr.Tag == tag { + if *nocgo { + fmt.Fprintf(w, "\t_mkcgo_%s = 0\n", fn.Name) + } else { + fmt.Fprintf(w, "\t_g_%s = NULL;\n", fn.ImportName()) + } + break + } + } + } + fmt.Fprintf(w, "}\n\n") + } + } +} diff --git a/cmd/mkcgo/main.go b/cmd/mkcgo/main.go index 86a5d8be..2f60545a 100644 --- a/cmd/mkcgo/main.go +++ b/cmd/mkcgo/main.go @@ -18,7 +18,11 @@ var ( fileName = flag.String("out", "", "output file name (standard output if omitted)") includeHeader = flag.String("include", "", "include header file") packageName = flag.String("package", "", "package name") + nocgo = flag.Bool("nocgo", false, "don't use cgo") + mode = flag.String("mode", "dynamic", "symbol load mode: dynamic, dynload") private = flag.Bool("private", false, "all Go generated symbols are kept unexported") + noerrors = flag.Bool("noerrors", false, "disable error handling") + extratags = flag.String("tags", "", "tags to add to the generated files") ) func usage() { @@ -28,6 +32,14 @@ func usage() { os.Exit(1) } +func dynamic() bool { + return *mode == "dynamic" +} + +func dynload() bool { + return *mode == "dynload" +} + func main() { // Set up and parse flags. flag.Usage = usage @@ -57,6 +69,57 @@ func main() { return cmp.Compare(a.Name, b.Name) }) + if *nocgo { + // Generate nocgo mode files + var nocgoGoBuffer, assemblyBuffer bytes.Buffer + generateNocgoGo(&src, &nocgoGoBuffer) + + // Only generate assembly if needed (i.e., not all functions are static) + needsAsm := needsAssembly() + if needsAsm { + generateAssembly(&src, &assemblyBuffer) + } + + // Format the generated Go source code. + nocgoGoData := goformat(nocgoGoBuffer.Bytes()) + + // Determine suffix based on the base name + suffix := "_nocgo.go" + + files := []struct { + suffix string + data []byte + }{ + {suffix, nocgoGoData}, + } + + // Only add assembly file if needed + if needsAsm { + files = append(files, struct { + suffix string + data []byte + }{".s", assemblyBuffer.Bytes()}) + } + + for _, d := range files { + name := autogeneratedFileName(d.suffix) + var err error + if *fileName == "" { + // Write output. If no explicit output file is specified, + // write both Go and assembly output to stdout. + os.Stdout.WriteString("// === " + name + " ===\n\n") + _, err = os.Stdout.Write(d.data) + } else { + err = os.WriteFile(name, d.data, 0o644) + } + if err != nil { + log.Fatal(err) + } + } + + return + } + var gobuf, go124buf, hbuf, cbuf bytes.Buffer generateGo(&src, &gobuf) generateGo124(&src, &go124buf) @@ -121,7 +184,7 @@ func writeTempSourceFile(data []byte) (string, error) { } func goformat(data []byte) []byte { - data, err := format.Source(data) + fdata, err := format.Source(data) if err != nil { log.Printf("failed to format source: %v", err) f, err := writeTempSourceFile(data) @@ -130,5 +193,5 @@ func goformat(data []byte) []byte { } log.Fatalf("for diagnosis, wrote unformatted source to %v", f) } - return data + return fdata } diff --git a/const.go b/const.go index 9f99a9dc..0bd0e696 100644 --- a/const.go +++ b/const.go @@ -1,6 +1,5 @@ package openssl -import "C" import "unsafe" // cString is a null-terminated string, diff --git a/des.go b/des.go index 78ecb988..772800a7 100644 --- a/des.go +++ b/des.go @@ -2,7 +2,6 @@ package openssl -import "C" import ( "crypto/cipher" "errors" diff --git a/des_test.go b/des_test.go index 6329d19e..06814d76 100644 --- a/des_test.go +++ b/des_test.go @@ -5,8 +5,8 @@ import ( "crypto/cipher" "testing" - "github.com/golang-fips/openssl/v2/internal/cryptotest" "github.com/golang-fips/openssl/v2" + "github.com/golang-fips/openssl/v2/internal/cryptotest" ) type CryptTest struct { diff --git a/dsa.go b/dsa.go index 37663591..921a51ab 100644 --- a/dsa.go +++ b/dsa.go @@ -2,7 +2,6 @@ package openssl -import "C" import ( "runtime" "unsafe" diff --git a/ec.go b/ec.go index 1a4e89dc..c560540a 100644 --- a/ec.go +++ b/ec.go @@ -2,7 +2,6 @@ package openssl -import "C" import "github.com/golang-fips/openssl/v2/internal/ossl" func curveNID(curve string) int32 { diff --git a/ecdh.go b/ecdh.go index d80d8b15..4a70754b 100644 --- a/ecdh.go +++ b/ecdh.go @@ -2,7 +2,6 @@ package openssl -import "C" import ( "errors" "runtime" @@ -96,7 +95,7 @@ func (k *PrivateKeyECDH) PublicKey() (*PublicKeyECDH, error) { if err != nil { return nil, err } - bytes = C.GoBytes(unsafe.Pointer(cbytes), C.int(n)) + bytes = goBytes(unsafe.Pointer(cbytes), int(n)) cryptoFree(unsafe.Pointer(cbytes)) default: panic(errUnsupportedVersion()) diff --git a/ecdsa.go b/ecdsa.go index e4d504de..34752741 100644 --- a/ecdsa.go +++ b/ecdsa.go @@ -2,7 +2,6 @@ package openssl -import "C" import ( "crypto" "errors" diff --git a/ed25519.go b/ed25519.go index 50fd06e5..f5b6b293 100644 --- a/ed25519.go +++ b/ed25519.go @@ -2,7 +2,6 @@ package openssl -import "C" import ( "errors" "runtime" diff --git a/evp.go b/evp.go index a6ad5590..d2fa83f1 100644 --- a/evp.go +++ b/evp.go @@ -2,7 +2,6 @@ package openssl -import "C" import ( "crypto" "errors" @@ -182,7 +181,7 @@ func loadHash(ch crypto.Hash) *hashAlgorithm { case 3: if prov := ossl.EVP_MD_get0_provider(hash.md); prov != nil { cname := ossl.OSSL_PROVIDER_get0_name(prov) - switch C.GoString((*C.char)(unsafe.Pointer(cname))) { + switch goString(cname) { case "default": hash.provider = providerOSSLDefault hash.marshallable = hash.magic != "" diff --git a/hash.go b/hash.go index 3c4db5fe..93383487 100644 --- a/hash.go +++ b/hash.go @@ -2,7 +2,6 @@ package openssl -import "C" import ( "crypto" "errors" diff --git a/hkdf.go b/hkdf.go index e95268a3..3c223ba9 100644 --- a/hkdf.go +++ b/hkdf.go @@ -2,7 +2,6 @@ package openssl -import "C" import ( "errors" "hash" diff --git a/hkdf_test.go b/hkdf_test.go index 3e9e93f8..6b66d303 100644 --- a/hkdf_test.go +++ b/hkdf_test.go @@ -450,11 +450,11 @@ func TestExpandHKDFOneShotLimit(t *testing.T) { } type tls13kdfTest struct { - hash func() hash.Hash - prk []byte - label []byte - ctx []byte - out []byte + hash func() hash.Hash + prk []byte + label []byte + ctx []byte + out []byte } var tls13kdfTests = []tls13kdfTest{ @@ -466,7 +466,7 @@ var tls13kdfTests = []tls13kdfTest{ 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5, }, - []byte("res binder") , + []byte("res binder"), []byte{}, []byte{ 0x10, 0x6d, 0x4e, 0xea, 0x65, 0x19, 0x16, 0xc7, @@ -485,7 +485,7 @@ var tls13kdfTests = []tls13kdfTest{ 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5, }, - []byte("c e traffic") , + []byte("c e traffic"), []byte{}, []byte{ 0x7e, 0xb6, 0x59, 0x96, 0x14, 0xf4, 0x1a, 0x27, @@ -504,7 +504,7 @@ var tls13kdfTests = []tls13kdfTest{ 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5, }, - []byte("c hs traffic") , + []byte("c hs traffic"), []byte{}, []byte{ 0x1f, 0xf4, 0xeb, 0xec, 0xca, 0x5b, 0x6f, 0x1c, @@ -523,7 +523,7 @@ var tls13kdfTests = []tls13kdfTest{ 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5, }, - []byte("s hs traffic") , + []byte("s hs traffic"), []byte{}, []byte{ 0xe9, 0xe4, 0x51, 0x4b, 0xe9, 0x0d, 0xb0, 0x44, @@ -542,7 +542,7 @@ var tls13kdfTests = []tls13kdfTest{ 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5, }, - []byte("c ap traffic") , + []byte("c ap traffic"), []byte{}, []byte{ 0x51, 0xee, 0xb6, 0x24, 0x50, 0x5f, 0x88, 0xdb, @@ -561,7 +561,7 @@ var tls13kdfTests = []tls13kdfTest{ 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5, }, - []byte("s ap traffic") , + []byte("s ap traffic"), []byte{}, []byte{ 0x08, 0x8c, 0xff, 0x31, 0xa0, 0xa1, 0x64, 0xca, @@ -580,7 +580,7 @@ var tls13kdfTests = []tls13kdfTest{ 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5, }, - []byte("e exp master") , + []byte("e exp master"), []byte{}, []byte{ 0x32, 0x59, 0x33, 0x2c, 0xf3, 0xb0, 0xc2, 0x0d, @@ -599,7 +599,7 @@ var tls13kdfTests = []tls13kdfTest{ 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5, }, - []byte("exp master") , + []byte("exp master"), []byte{}, []byte{ 0x50, 0x6a, 0x2e, 0xe3, 0x95, 0x77, 0x6c, 0xfb, @@ -618,7 +618,7 @@ var tls13kdfTests = []tls13kdfTest{ 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5, }, - []byte("res master") , + []byte("res master"), []byte{}, []byte{ 0xc1, 0x37, 0xab, 0x0f, 0x7b, 0x58, 0xb7, 0xe9, diff --git a/hmac.go b/hmac.go index f600f0f4..7ef4c426 100644 --- a/hmac.go +++ b/hmac.go @@ -2,7 +2,6 @@ package openssl -import "C" import ( "hash" "runtime" diff --git a/init.go b/init.go index 3ea2a896..52dac619 100644 --- a/init.go +++ b/init.go @@ -2,7 +2,6 @@ package openssl -import "C" import ( "errors" "unsafe" diff --git a/init_nocgo_unix.go b/init_nocgo_unix.go new file mode 100644 index 00000000..19609e23 --- /dev/null +++ b/init_nocgo_unix.go @@ -0,0 +1,32 @@ +//go:build unix && !cmd_go_bootstrap && !cgo + +package openssl + +import ( + "errors" + "runtime" + "unsafe" + + "github.com/golang-fips/openssl/v2/internal/ossl" +) + +func dlopen(file string) (handle unsafe.Pointer, err error) { + const RTLD_LAZY = 1 + var RTLD_LOCAL = 0 + if runtime.GOOS == "darwin" { + RTLD_LOCAL = 4 // darwin uses 4 as RTLD_LOCAL + } + handle = ossl.Dlopen(unsafe.StringData(file+"\x00"), int32(RTLD_LAZY|RTLD_LOCAL)) + if handle == nil { + return nil, errors.New(goString(ossl.Dlerror())) + } + return handle, nil +} + +func dlclose(handle unsafe.Pointer) error { + if ossl.Dlclose(handle) != 0 { + errstr := goString(ossl.Dlerror()) + return errors.New("openssl: can't close libcrypto: " + errstr) + } + return nil +} diff --git a/init_unix.go b/init_unix.go index dbf5ac44..ab376df2 100644 --- a/init_unix.go +++ b/init_unix.go @@ -1,4 +1,4 @@ -//go:build unix && !cmd_go_bootstrap +//go:build unix && !cmd_go_bootstrap && cgo package openssl diff --git a/internal/fakecgo/abi_amd64.h b/internal/fakecgo/abi_amd64.h new file mode 100644 index 00000000..49931928 --- /dev/null +++ b/internal/fakecgo/abi_amd64.h @@ -0,0 +1,34 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Macros for transitioning from the host ABI to Go ABI0. +// +// These save the frame pointer, so in general, functions that use +// these should have zero frame size to suppress the automatic frame +// pointer, though it's harmless to not do this. + +#define REGS_HOST_TO_ABI0_STACK (6*8) + +// SysV MXCSR matches the Go ABI, so we don't have to set that, +// and Go doesn't modify it, so we don't have to save it. +// Both SysV and Go require DF to be cleared, so that's already clear. +// The SysV and Go frame pointer conventions are compatible. +#define PUSH_REGS_HOST_TO_ABI0() \ + ADJSP $(REGS_HOST_TO_ABI0_STACK) \ + MOVQ BP, (5*8)(SP) \ + LEAQ (5*8)(SP), BP \ + MOVQ BX, (0*8)(SP) \ + MOVQ R12, (1*8)(SP) \ + MOVQ R13, (2*8)(SP) \ + MOVQ R14, (3*8)(SP) \ + MOVQ R15, (4*8)(SP) + +#define POP_REGS_HOST_TO_ABI0() \ + MOVQ (0*8)(SP), BX \ + MOVQ (1*8)(SP), R12 \ + MOVQ (2*8)(SP), R13 \ + MOVQ (3*8)(SP), R14 \ + MOVQ (4*8)(SP), R15 \ + MOVQ (5*8)(SP), BP \ + ADJSP $-(REGS_HOST_TO_ABI0_STACK) diff --git a/internal/fakecgo/abi_arm64.h b/internal/fakecgo/abi_arm64.h new file mode 100644 index 00000000..b7bc85e3 --- /dev/null +++ b/internal/fakecgo/abi_arm64.h @@ -0,0 +1,39 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Macros for transitioning from the host ABI to Go ABI0. +// +// These macros save and restore the callee-saved registers +// from the stack, but they don't adjust stack pointer, so +// the user should prepare stack space in advance. +// SAVE_R19_TO_R28(offset) saves R19 ~ R28 to the stack space +// of ((offset)+0*8)(RSP) ~ ((offset)+9*8)(RSP). +// +// SAVE_F8_TO_F15(offset) saves F8 ~ F15 to the stack space +// of ((offset)+0*8)(RSP) ~ ((offset)+7*8)(RSP). +// +// R29 is not saved because Go will save and restore it. + +#define SAVE_R19_TO_R28(offset) \ + STP (R19, R20), ((offset)+0*8)(RSP) \ + STP (R21, R22), ((offset)+2*8)(RSP) \ + STP (R23, R24), ((offset)+4*8)(RSP) \ + STP (R25, R26), ((offset)+6*8)(RSP) \ + STP (R27, g), ((offset)+8*8)(RSP) +#define RESTORE_R19_TO_R28(offset) \ + LDP ((offset)+0*8)(RSP), (R19, R20) \ + LDP ((offset)+2*8)(RSP), (R21, R22) \ + LDP ((offset)+4*8)(RSP), (R23, R24) \ + LDP ((offset)+6*8)(RSP), (R25, R26) \ + LDP ((offset)+8*8)(RSP), (R27, g) /* R28 */ +#define SAVE_F8_TO_F15(offset) \ + FSTPD (F8, F9), ((offset)+0*8)(RSP) \ + FSTPD (F10, F11), ((offset)+2*8)(RSP) \ + FSTPD (F12, F13), ((offset)+4*8)(RSP) \ + FSTPD (F14, F15), ((offset)+6*8)(RSP) +#define RESTORE_F8_TO_F15(offset) \ + FLDPD ((offset)+0*8)(RSP), (F8, F9) \ + FLDPD ((offset)+2*8)(RSP), (F10, F11) \ + FLDPD ((offset)+4*8)(RSP), (F12, F13) \ + FLDPD ((offset)+6*8)(RSP), (F14, F15) diff --git a/internal/fakecgo/asm_amd64.s b/internal/fakecgo/asm_amd64.s new file mode 100644 index 00000000..5c51e0df --- /dev/null +++ b/internal/fakecgo/asm_amd64.s @@ -0,0 +1,29 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" +#include "abi_amd64.h" + +// Called by C code generated by cmd/cgo. +// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr) +// Saves C callee-saved registers and calls cgocallback with three arguments. +// fn is the PC of a func(a unsafe.Pointer) function. +// This signature is known to SWIG, so we can't change it. +TEXT crosscall2(SB), NOSPLIT, $0-0 + PUSH_REGS_HOST_TO_ABI0() + + // Make room for arguments to cgocallback. + ADJSP $0x18 + + MOVQ DI, 0x0(SP) // fn + MOVQ SI, 0x8(SP) // arg + + // Skip n in DX. + MOVQ CX, 0x10(SP) // ctxt + + CALL runtime·cgocallback(SB) + + ADJSP $-0x18 + POP_REGS_HOST_TO_ABI0() + RET diff --git a/internal/fakecgo/asm_arm64.s b/internal/fakecgo/asm_arm64.s new file mode 100644 index 00000000..92626a45 --- /dev/null +++ b/internal/fakecgo/asm_arm64.s @@ -0,0 +1,36 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" +#include "abi_arm64.h" + +// Called by C code generated by cmd/cgo. +// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr) +// Saves C callee-saved registers and calls cgocallback with three arguments. +// fn is the PC of a func(a unsafe.Pointer) function. +TEXT crosscall2(SB), NOSPLIT|NOFRAME, $0 +/* + * We still need to save all callee save register as before, and then + * push 3 args for fn (R0, R1, R3), skipping R2. + * Also note that at procedure entry in gc world, 8(RSP) will be the + * first arg. + */ + SUB $(8*24), RSP + STP (R0, R1), (8*1)(RSP) + MOVD R3, (8*3)(RSP) + + SAVE_R19_TO_R28(8*4) + SAVE_F8_TO_F15(8*14) + STP (R29, R30), (8*22)(RSP) + + // Initialize Go ABI environment + BL runtime·load_g(SB) + BL runtime·cgocallback(SB) + + RESTORE_R19_TO_R28(8*4) + RESTORE_F8_TO_F15(8*14) + LDP (8*22)(RSP), (R29, R30) + + ADD $(8*24), RSP + RET diff --git a/internal/fakecgo/callbacks.go b/internal/fakecgo/callbacks.go new file mode 100644 index 00000000..fc12723d --- /dev/null +++ b/internal/fakecgo/callbacks.go @@ -0,0 +1,93 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !cgo && (darwin || linux) + +package fakecgo + +import ( + _ "unsafe" +) + +// TODO: decide if we need _runtime_cgo_panic_internal + +//go:linkname x_cgo_init_trampoline x_cgo_init_trampoline +//go:linkname _cgo_init _cgo_init +var x_cgo_init_trampoline byte +var _cgo_init = &x_cgo_init_trampoline + +// Creates a new system thread without updating any Go state. +// +// This method is invoked during shared library loading to create a new OS +// thread to perform the runtime initialization. This method is similar to +// _cgo_sys_thread_start except that it doesn't update any Go state. + +//go:linkname x_cgo_thread_start_trampoline x_cgo_thread_start_trampoline +//go:linkname _cgo_thread_start _cgo_thread_start +var x_cgo_thread_start_trampoline byte +var _cgo_thread_start = &x_cgo_thread_start_trampoline + +// Notifies that the runtime has been initialized. +// +// We currently block at every CGO entry point (via _cgo_wait_runtime_init_done) +// to ensure that the runtime has been initialized before the CGO call is +// executed. This is necessary for shared libraries where we kickoff runtime +// initialization in a separate thread and return without waiting for this +// thread to complete the init. + +//go:linkname x_cgo_notify_runtime_init_done_trampoline x_cgo_notify_runtime_init_done_trampoline +//go:linkname _cgo_notify_runtime_init_done _cgo_notify_runtime_init_done +var x_cgo_notify_runtime_init_done_trampoline byte +var _cgo_notify_runtime_init_done = &x_cgo_notify_runtime_init_done_trampoline + +// Indicates whether a dummy thread key has been created or not. +// +// When calling go exported function from C, we register a destructor +// callback, for a dummy thread key, by using pthread_key_create. + +//go:linkname _cgo_pthread_key_created _cgo_pthread_key_created +var x_cgo_pthread_key_created uintptr +var _cgo_pthread_key_created = &x_cgo_pthread_key_created + +// Set the x_crosscall2_ptr C function pointer variable point to crosscall2. +// It's for the runtime package to call at init time. +func set_crosscall2() { + // nothing needs to be done here for fakecgo + // because it's possible to just call cgocallback directly +} + +//go:linkname _set_crosscall2 runtime.set_crosscall2 +var _set_crosscall2 = set_crosscall2 + +// Store the g into the thread-specific value. +// So that pthread_key_destructor will dropm when the thread is exiting. + +//go:linkname x_cgo_bindm_trampoline x_cgo_bindm_trampoline +//go:linkname _cgo_bindm _cgo_bindm +var x_cgo_bindm_trampoline byte +var _cgo_bindm = &x_cgo_bindm_trampoline + +// TODO: decide if we need x_cgo_set_context_function +// TODO: decide if we need _cgo_yield + +var ( + // In Go 1.20 the race detector was rewritten to pure Go + // on darwin. This means that when CGO_ENABLED=0 is set + // fakecgo is built with race detector code. This is not + // good since this code is pretending to be C. The go:norace + // pragma is not enough, since it only applies to the native + // ABIInternal function. The ABIO wrapper (which is necessary, + // since all references to text symbols from assembly will use it) + // does not inherit the go:norace pragma, so it will still be + // instrumented by the race detector. + // + // To circumvent this issue, using closure calls in the + // assembly, which forces the compiler to use the ABIInternal + // native implementation (which has go:norace) instead. + threadentry_call = threadentry + x_cgo_init_call = x_cgo_init + x_cgo_setenv_call = x_cgo_setenv + x_cgo_unsetenv_call = x_cgo_unsetenv + x_cgo_thread_start_call = x_cgo_thread_start +) diff --git a/internal/fakecgo/doc.go b/internal/fakecgo/doc.go new file mode 100644 index 00000000..ef0c28b3 --- /dev/null +++ b/internal/fakecgo/doc.go @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2022 The Ebitengine Authors + +//go:build !cgo && (darwin || linux) + +// Package fakecgo implements the Cgo runtime (runtime/cgo) entirely in Go. +// This allows code that calls into C to function properly when CGO_ENABLED=0. +// +// # Goals +// +// fakecgo attempts to replicate the same naming structure as in the runtime. +// For example, functions that have the prefix "gcc_*" are named "go_*". +// This makes it easier to port other GOOSs and GOARCHs as well as to keep +// it in sync with runtime/cgo. +// +// # Support +// +// Currently, fakecgo only supports macOS on amd64 & arm64. It also cannot +// be used with -buildmode=c-archive because that requires special initialization +// that fakecgo does not implement at the moment. +// +// # Usage +// +// Using fakecgo is easy just import _ "github.com/ebitengine/purego" and then +// set the environment variable CGO_ENABLED=0. +// The recommended usage for fakecgo is to prefer using runtime/cgo if possible +// but if cross-compiling or fast build times are important fakecgo is available. +// Purego will pick which ever Cgo runtime is available and prefer the one that +// comes with Go (runtime/cgo). +package fakecgo + +//go:generate go run gen.go diff --git a/internal/fakecgo/gen.go b/internal/fakecgo/gen.go new file mode 100644 index 00000000..dba3b445 --- /dev/null +++ b/internal/fakecgo/gen.go @@ -0,0 +1,245 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2022 The Ebitengine Authors + +//go:build ignore + +package main + +import ( + "bytes" + "fmt" + "go/format" + "log" + "os" + "strings" + "text/template" +) + +const templateSymbols = `// Code generated by 'go generate' with gen.go. DO NOT EDIT. + +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2022 The Ebitengine Authors + +//go:build !cgo && (darwin || linux) + +package fakecgo + +import ( + "syscall" + "unsafe" +) + +// setg_trampoline calls setg with the G provided +func setg_trampoline(setg uintptr, G uintptr) + +// call5 takes fn the C function and 5 arguments and calls the function with those arguments +func call5(fn, a1, a2, a3, a4, a5 uintptr) uintptr + +{{ range . -}} +//go:nosplit +//go:norace +func {{.Name}}( +{{- range .Args -}} + {{- if .Name -}} + {{.Name}} {{.Type}}, + {{- end -}} +{{- end -}}) {{.Return}} { + {{- if .Return -}} + {{- if eq .Return "unsafe.Pointer" -}} + ret := + {{- else -}} + return {{.Return}}( + {{- end -}} + {{- end -}} +call5({{.Name}}ABI0, +{{- range .Args}} + {{- if .Name -}} + {{- if hasPrefix .Type "*" -}} + uintptr(unsafe.Pointer({{.Name}})), + {{- else -}} + uintptr({{.Name}}), + {{- end -}} + {{- else -}} + 0, + {{- end -}} +{{- end -}} + ) {{/* end of call5 */}} +{{- if .Return -}} + {{- if eq .Return "unsafe.Pointer"}} + // this indirection is to avoid go vet complaining about possible misuse of unsafe.Pointer + return *(*unsafe.Pointer)(unsafe.Pointer(&ret)) + {{- else -}} + ) {{/* end of cast */}} + {{- end -}} +{{- end}} +} + +{{end}} +{{- range . }} +//go:linkname _{{.Name}} _{{.Name}} +var _{{.Name}} uint8 +var {{.Name}}ABI0 = uintptr(unsafe.Pointer(&_{{.Name}})) +{{ end }} +` + +const templateTrampolinesStubs = `// Code generated by 'go generate' with gen.go. DO NOT EDIT. + +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2022 The Ebitengine Authors + +//go:build !cgo && (darwin || linux) + +#include "textflag.h" + +// these stubs are here because it is not possible to go:linkname directly the C functions on darwin arm64 +{{ range . }} +TEXT _{{.Name}}(SB), NOSPLIT|NOFRAME, $0-0 + JMP purego_{{.Name}}(SB) + RET +{{ end -}} +` + +const templateSymbolsGoos = `// Code generated by 'go generate' with gen.go. DO NOT EDIT. + +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2022 The Ebitengine Authors + +//go:build !cgo + +package fakecgo + +{{- range $location := . }} +{{- range .Symbols }} +//go:cgo_import_dynamic purego_{{ .Name }} {{ .Name }} "{{ $location.SharedObject }}" +{{- end }} +{{- end }} +` + +type Arg struct { + Name string + Type string +} + +type Symbol struct { + Name string + Args [5]Arg + Return string +} + +type LocatedSymbols struct { + SharedObject string + Symbols []Symbol +} + +var ( + libcSymbols = []Symbol{ + {"malloc", [5]Arg{{"size", "uintptr"}}, "unsafe.Pointer"}, + {"free", [5]Arg{{"ptr", "unsafe.Pointer"}}, ""}, + {"setenv", [5]Arg{{"name", "*byte"}, {"value", "*byte"}, {"overwrite", "int32"}}, "int32"}, + {"unsetenv", [5]Arg{{"name", "*byte"}}, "int32"}, + {"sigfillset", [5]Arg{{"set", "*sigset_t"}}, "int32"}, + {"nanosleep", [5]Arg{{"ts", "*syscall.Timespec"}, {"rem", "*syscall.Timespec"}}, "int32"}, + {"abort", [5]Arg{}, ""}, + {"sigaltstack", [5]Arg{{"ss", "*stack_t"}, {"old_ss", "*stack_t"}}, "int32"}, + } + pthreadSymbols = []Symbol{ + {"pthread_attr_init", [5]Arg{{"attr", "*pthread_attr_t"}}, "int32"}, + {"pthread_create", [5]Arg{{"thread", "*pthread_t"}, {"attr", "*pthread_attr_t"}, {"start", "unsafe.Pointer"}, {"arg", "unsafe.Pointer"}}, "int32"}, + {"pthread_detach", [5]Arg{{"thread", "pthread_t"}}, "int32"}, + {"pthread_sigmask", [5]Arg{{"how", "sighow"}, {"ign", "*sigset_t"}, {"oset", "*sigset_t"}}, "int32"}, + {"pthread_self", [5]Arg{}, "pthread_t"}, + {"pthread_get_stacksize_np", [5]Arg{{"thread", "pthread_t"}}, "size_t"}, + {"pthread_attr_getstacksize", [5]Arg{{"attr", "*pthread_attr_t"}, {"stacksize", "*size_t"}}, "int32"}, + {"pthread_attr_setstacksize", [5]Arg{{"attr", "*pthread_attr_t"}, {"size", "size_t"}}, "int32"}, + {"pthread_attr_destroy", [5]Arg{{"attr", "*pthread_attr_t"}}, "int32"}, + {"pthread_mutex_lock", [5]Arg{{"mutex", "*pthread_mutex_t"}}, "int32"}, + {"pthread_mutex_unlock", [5]Arg{{"mutex", "*pthread_mutex_t"}}, "int32"}, + {"pthread_cond_broadcast", [5]Arg{{"cond", "*pthread_cond_t"}}, "int32"}, + {"pthread_setspecific", [5]Arg{{"key", "pthread_key_t"}, {"value", "unsafe.Pointer"}}, "int32"}, + } +) + +var funcs = map[string]any{ + "hasPrefix": strings.HasPrefix, +} + +func run() error { + t, err := template.New("symbol.go").Funcs(funcs).Parse(templateSymbols) + if err != nil { + return err + } + f, err := os.Create("symbols.go") + defer f.Close() + if err != nil { + return err + } + allSymbols := append(append([]Symbol{}, libcSymbols...), pthreadSymbols...) + buf := new(bytes.Buffer) + if err := t.Execute(buf, allSymbols); err != nil { + return err + } + source, err := format.Source(buf.Bytes()) + if err != nil { + return err + } + if _, err = f.Write(source); err != nil { + return err + } + t, err = template.New("trampolines_stubs.s").Funcs(funcs).Parse(templateTrampolinesStubs) + if err != nil { + return err + } + f, err = os.Create("trampolines_stubs.s") + defer f.Close() + if err != nil { + return err + } + if err := t.Execute(f, allSymbols); err != nil { + return err + } + t, err = template.New("symbols_goos.go").Parse(templateSymbolsGoos) + if err != nil { + return err + } + for _, goos := range []string{"darwin", "linux"} { + f, err = os.Create(fmt.Sprintf("symbols_%s.go", goos)) + defer f.Close() + if err != nil { + return err + } + b := &bytes.Buffer{} + var libcSO, pthreadSO string + switch goos { + case "darwin": + libcSO = "/usr/lib/libSystem.B.dylib" + pthreadSO = "/usr/lib/libSystem.B.dylib" + case "linux": + libcSO = "libc.so.6" + pthreadSO = "libpthread.so.0" + default: + return fmt.Errorf("unsupported OS: %s", goos) + } + located := []LocatedSymbols{ + {SharedObject: libcSO, Symbols: libcSymbols}, + {SharedObject: pthreadSO, Symbols: pthreadSymbols}, + } + if err = t.Execute(b, located); err != nil { + return err + } + var src []byte + src, err = format.Source(b.Bytes()) + if err != nil { + return err + } + if _, err = f.Write(src); err != nil { + return err + } + } + return nil +} + +func main() { + if err := run(); err != nil { + log.Fatal(err) + } +} diff --git a/internal/fakecgo/go_darwin.go b/internal/fakecgo/go_darwin.go new file mode 100644 index 00000000..e9852c91 --- /dev/null +++ b/internal/fakecgo/go_darwin.go @@ -0,0 +1,73 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !cgo + +package fakecgo + +import "unsafe" + +//go:nosplit +//go:norace +func _cgo_sys_thread_start(ts *ThreadStart) { + var attr pthread_attr_t + var ign, oset sigset_t + var p pthread_t + var size size_t + var err int + + sigfillset(&ign) + pthread_sigmask(SIG_SETMASK, &ign, &oset) + + size = pthread_get_stacksize_np(pthread_self()) + pthread_attr_init(&attr) + pthread_attr_setstacksize(&attr, size) + // Leave stacklo=0 and set stackhi=size; mstart will do the rest. + ts.g.stackhi = uintptr(size) + + err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts) + + pthread_sigmask(SIG_SETMASK, &oset, nil) + + if err != 0 { + print("fakecgo: pthread_create failed: ") + println(err) + abort() + } +} + +// threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function +// +//go:linkname x_threadentry_trampoline threadentry_trampoline +var x_threadentry_trampoline byte +var threadentry_trampolineABI0 = &x_threadentry_trampoline + +//go:nosplit +//go:norace +func threadentry(v unsafe.Pointer) unsafe.Pointer { + ts := *(*ThreadStart)(v) + free(v) + + setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g))) + + // faking funcs in go is a bit a... involved - but the following works :) + fn := uintptr(unsafe.Pointer(&ts.fn)) + (*(*func())(unsafe.Pointer(&fn)))() + + return nil +} + +// here we will store a pointer to the provided setg func +var setg_func uintptr + +//go:nosplit +//go:norace +func x_cgo_init(g *G, setg uintptr) { + var size size_t + + setg_func = setg + + size = pthread_get_stacksize_np(pthread_self()) + g.stacklo = uintptr(unsafe.Add(unsafe.Pointer(&size), -size+4096)) +} diff --git a/internal/fakecgo/go_libinit.go b/internal/fakecgo/go_libinit.go new file mode 100644 index 00000000..c33d4c0d --- /dev/null +++ b/internal/fakecgo/go_libinit.go @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2022 The Ebitengine Authors + +//go:build !cgo && (darwin || linux) + +package fakecgo + +import ( + "syscall" + "unsafe" +) + +var ( + pthread_g pthread_key_t + + runtime_init_cond = PTHREAD_COND_INITIALIZER + runtime_init_mu = PTHREAD_MUTEX_INITIALIZER + runtime_init_done int +) + +//go:nosplit +//go:norace +func x_cgo_notify_runtime_init_done() { + pthread_mutex_lock(&runtime_init_mu) + runtime_init_done = 1 + pthread_cond_broadcast(&runtime_init_cond) + pthread_mutex_unlock(&runtime_init_mu) +} + +// Store the g into a thread-specific value associated with the pthread key pthread_g. +// And pthread_key_destructor will dropm when the thread is exiting. +// +//go:norace +func x_cgo_bindm(g unsafe.Pointer) { + // We assume this will always succeed, otherwise, there might be extra M leaking, + // when a C thread exits after a cgo call. + // We only invoke this function once per thread in runtime.needAndBindM, + // and the next calls just reuse the bound m. + pthread_setspecific(pthread_g, g) +} + +// _cgo_try_pthread_create retries pthread_create if it fails with +// EAGAIN. +// +//go:nosplit +//go:norace +func _cgo_try_pthread_create(thread *pthread_t, attr *pthread_attr_t, pfn unsafe.Pointer, arg *ThreadStart) int { + var ts syscall.Timespec + // tries needs to be the same type as syscall.Timespec.Nsec + // but the fields are int32 on 32bit and int64 on 64bit. + // tries is assigned to syscall.Timespec.Nsec in order to match its type. + tries := ts.Nsec + var err int + + for tries = 0; tries < 20; tries++ { + // inlined this call because it ran out of stack when inlining was disabled + err = int(call5(pthread_createABI0, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(pfn), uintptr(unsafe.Pointer(arg)), 0)) + if err == 0 { + // inlined this call because it ran out of stack when inlining was disabled + call5(pthread_detachABI0, uintptr(*thread), 0, 0, 0, 0) + return 0 + } + if err != int(syscall.EAGAIN) { + return err + } + ts.Sec = 0 + ts.Nsec = (tries + 1) * 1000 * 1000 // Milliseconds. + // inlined this call because it ran out of stack when inlining was disabled + call5(nanosleepABI0, uintptr(unsafe.Pointer(&ts)), 0, 0, 0, 0) + } + return int(syscall.EAGAIN) +} diff --git a/internal/fakecgo/go_linux.go b/internal/fakecgo/go_linux.go new file mode 100644 index 00000000..15348b3d --- /dev/null +++ b/internal/fakecgo/go_linux.go @@ -0,0 +1,95 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !cgo + +package fakecgo + +import "unsafe" + +//go:nosplit +func _cgo_sys_thread_start(ts *ThreadStart) { + var attr pthread_attr_t + var ign, oset sigset_t + var p pthread_t + var size size_t + var err int + + //fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug + sigfillset(&ign) + pthread_sigmask(SIG_SETMASK, &ign, &oset) + + pthread_attr_init(&attr) + pthread_attr_getstacksize(&attr, &size) + // Leave stacklo=0 and set stackhi=size; mstart will do the rest. + ts.g.stackhi = uintptr(size) + + err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts) + + pthread_sigmask(SIG_SETMASK, &oset, nil) + + if err != 0 { + print("fakecgo: pthread_create failed: ") + println(err) + abort() + } +} + +// threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function +// +//go:linkname x_threadentry_trampoline threadentry_trampoline +var x_threadentry_trampoline byte +var threadentry_trampolineABI0 = &x_threadentry_trampoline + +//go:nosplit +func threadentry(v unsafe.Pointer) unsafe.Pointer { + ts := *(*ThreadStart)(v) + free(v) + + setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g))) + + // faking funcs in go is a bit a... involved - but the following works :) + fn := uintptr(unsafe.Pointer(&ts.fn)) + (*(*func())(unsafe.Pointer(&fn)))() + + return nil +} + +// here we will store a pointer to the provided setg func +var setg_func uintptr + +//go:nosplit +func x_cgo_init(g *G, setg uintptr) { + var size size_t + var attr *pthread_attr_t + + /* The memory sanitizer distributed with versions of clang + before 3.8 has a bug: if you call mmap before malloc, mmap + may return an address that is later overwritten by the msan + library. Avoid this problem by forcing a call to malloc + here, before we ever call malloc. + + This is only required for the memory sanitizer, so it's + unfortunate that we always run it. It should be possible + to remove this when we no longer care about versions of + clang before 3.8. The test for this is + misc/cgo/testsanitizers. + + GCC works hard to eliminate a seemingly unnecessary call to + malloc, so we actually use the memory we allocate. */ + + setg_func = setg + attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr))) + if attr == nil { + println("fakecgo: malloc failed") + abort() + } + pthread_attr_init(attr) + pthread_attr_getstacksize(attr, &size) + // runtime/cgo uses __builtin_frame_address(0) instead of `uintptr(unsafe.Pointer(&size))` + // but this should be OK since we are taking the address of the first variable in this function. + g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096 + pthread_attr_destroy(attr) + free(unsafe.Pointer(attr)) +} diff --git a/internal/fakecgo/go_setenv.go b/internal/fakecgo/go_setenv.go new file mode 100644 index 00000000..43cd6aa6 --- /dev/null +++ b/internal/fakecgo/go_setenv.go @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2022 The Ebitengine Authors + +//go:build !cgo && (darwin || linux) + +package fakecgo + +//go:nosplit +//go:norace +func x_cgo_setenv(arg *[2]*byte) { + setenv(arg[0], arg[1], 1) +} + +//go:nosplit +//go:norace +func x_cgo_unsetenv(arg *[1]*byte) { + unsetenv(arg[0]) +} diff --git a/internal/fakecgo/go_util.go b/internal/fakecgo/go_util.go new file mode 100644 index 00000000..de117954 --- /dev/null +++ b/internal/fakecgo/go_util.go @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2022 The Ebitengine Authors + +//go:build !cgo && (darwin || linux) + +package fakecgo + +import "unsafe" + +// _cgo_thread_start is split into three parts in cgo since only one part is system dependent (keep it here for easier handling) + +// _cgo_thread_start(ThreadStart *arg) (runtime/cgo/gcc_util.c) +// This get's called instead of the go code for creating new threads +// -> pthread_* stuff is used, so threads are setup correctly for C +// If this is missing, TLS is only setup correctly on thread 1! +// This function should be go:systemstack instead of go:nosplit (but that requires runtime) +// +//go:nosplit +//go:norace +func x_cgo_thread_start(arg *ThreadStart) { + var ts *ThreadStart + // Make our own copy that can persist after we return. + // _cgo_tsan_acquire(); + ts = (*ThreadStart)(malloc(unsafe.Sizeof(*ts))) + // _cgo_tsan_release(); + if ts == nil { + println("fakecgo: out of memory in thread_start") + abort() + } + // *ts = *arg would cause a writebarrier so copy using slices + s1 := unsafe.Slice((*uintptr)(unsafe.Pointer(ts)), unsafe.Sizeof(*ts)/8) + s2 := unsafe.Slice((*uintptr)(unsafe.Pointer(arg)), unsafe.Sizeof(*arg)/8) + for i := range s2 { + s1[i] = s2[i] + } + _cgo_sys_thread_start(ts) // OS-dependent half +} diff --git a/internal/fakecgo/iscgo.go b/internal/fakecgo/iscgo.go new file mode 100644 index 00000000..1fdf9ce7 --- /dev/null +++ b/internal/fakecgo/iscgo.go @@ -0,0 +1,19 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !cgo && (darwin || linux) + +// The runtime package contains an uninitialized definition +// for runtime·iscgo. Override it to tell the runtime we're here. +// There are various function pointers that should be set too, +// but those depend on dynamic linker magic to get initialized +// correctly, and sometimes they break. This variable is a +// backup: it depends only on old C style static linking rules. + +package fakecgo + +import _ "unsafe" // for go:linkname + +//go:linkname _iscgo runtime.iscgo +var _iscgo bool = true diff --git a/internal/fakecgo/libcgo.go b/internal/fakecgo/libcgo.go new file mode 100644 index 00000000..5e947e5a --- /dev/null +++ b/internal/fakecgo/libcgo.go @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2022 The Ebitengine Authors + +//go:build !cgo && (darwin || linux) + +package fakecgo + +type ( + size_t uintptr + // Sources: + // Darwin (32 bytes) - https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/bsd/sys/_types.h#L74 + // Linux (128 bytes) - https://github.com/torvalds/linux/blob/ab75170520d4964f3acf8bb1f91d34cbc650688e/arch/x86/include/asm/signal.h#L25 + sigset_t [128]byte + pthread_attr_t [64]byte + pthread_t int + pthread_key_t uint64 +) + +// for pthread_sigmask: + +type sighow int32 + +const ( + SIG_BLOCK sighow = 0 + SIG_UNBLOCK sighow = 1 + SIG_SETMASK sighow = 2 +) + +type G struct { + stacklo uintptr + stackhi uintptr +} + +type ThreadStart struct { + g *G + tls *uintptr + fn uintptr +} diff --git a/internal/fakecgo/libcgo_darwin.go b/internal/fakecgo/libcgo_darwin.go new file mode 100644 index 00000000..a31278e8 --- /dev/null +++ b/internal/fakecgo/libcgo_darwin.go @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2022 The Ebitengine Authors + +//go:build !cgo + +package fakecgo + +type ( + pthread_mutex_t struct { + sig int64 + opaque [56]byte + } + pthread_cond_t struct { + sig int64 + opaque [40]byte + } +) + +var ( + PTHREAD_COND_INITIALIZER = pthread_cond_t{sig: 0x3CB0B1BB} + PTHREAD_MUTEX_INITIALIZER = pthread_mutex_t{sig: 0x32AAABA7} +) + +type stack_t struct { + /* not implemented */ +} diff --git a/internal/fakecgo/libcgo_linux.go b/internal/fakecgo/libcgo_linux.go new file mode 100644 index 00000000..61948af5 --- /dev/null +++ b/internal/fakecgo/libcgo_linux.go @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2022 The Ebitengine Authors + +//go:build !cgo + +package fakecgo + +type ( + pthread_cond_t [48]byte + pthread_mutex_t [48]byte +) + +var ( + PTHREAD_COND_INITIALIZER = pthread_cond_t{} + PTHREAD_MUTEX_INITIALIZER = pthread_mutex_t{} +) + +type stack_t struct { + /* not implemented */ +} diff --git a/internal/fakecgo/setenv.go b/internal/fakecgo/setenv.go new file mode 100644 index 00000000..abb69e74 --- /dev/null +++ b/internal/fakecgo/setenv.go @@ -0,0 +1,19 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !cgo && (darwin || linux) + +package fakecgo + +import _ "unsafe" // for go:linkname + +//go:linkname x_cgo_setenv_trampoline x_cgo_setenv_trampoline +//go:linkname _cgo_setenv runtime._cgo_setenv +var x_cgo_setenv_trampoline byte +var _cgo_setenv = &x_cgo_setenv_trampoline + +//go:linkname x_cgo_unsetenv_trampoline x_cgo_unsetenv_trampoline +//go:linkname _cgo_unsetenv runtime._cgo_unsetenv +var x_cgo_unsetenv_trampoline byte +var _cgo_unsetenv = &x_cgo_unsetenv_trampoline diff --git a/internal/fakecgo/symbols.go b/internal/fakecgo/symbols.go new file mode 100644 index 00000000..74db9a39 --- /dev/null +++ b/internal/fakecgo/symbols.go @@ -0,0 +1,231 @@ +// Code generated by 'go generate' with gen.go. DO NOT EDIT. + +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2022 The Ebitengine Authors + +//go:build !cgo && (darwin || linux) + +package fakecgo + +import ( + "syscall" + "unsafe" +) + +// setg_trampoline calls setg with the G provided +func setg_trampoline(setg uintptr, G uintptr) + +// call5 takes fn the C function and 5 arguments and calls the function with those arguments +func call5(fn, a1, a2, a3, a4, a5 uintptr) uintptr + +//go:nosplit +//go:norace +func malloc(size uintptr) unsafe.Pointer { + ret := call5(mallocABI0, uintptr(size), 0, 0, 0, 0) + // this indirection is to avoid go vet complaining about possible misuse of unsafe.Pointer + return *(*unsafe.Pointer)(unsafe.Pointer(&ret)) +} + +//go:nosplit +//go:norace +func free(ptr unsafe.Pointer) { + call5(freeABI0, uintptr(ptr), 0, 0, 0, 0) +} + +//go:nosplit +//go:norace +func setenv(name *byte, value *byte, overwrite int32) int32 { + return int32(call5(setenvABI0, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), uintptr(overwrite), 0, 0)) +} + +//go:nosplit +//go:norace +func unsetenv(name *byte) int32 { + return int32(call5(unsetenvABI0, uintptr(unsafe.Pointer(name)), 0, 0, 0, 0)) +} + +//go:nosplit +//go:norace +func sigfillset(set *sigset_t) int32 { + return int32(call5(sigfillsetABI0, uintptr(unsafe.Pointer(set)), 0, 0, 0, 0)) +} + +//go:nosplit +//go:norace +func nanosleep(ts *syscall.Timespec, rem *syscall.Timespec) int32 { + return int32(call5(nanosleepABI0, uintptr(unsafe.Pointer(ts)), uintptr(unsafe.Pointer(rem)), 0, 0, 0)) +} + +//go:nosplit +//go:norace +func abort() { + call5(abortABI0, 0, 0, 0, 0, 0) +} + +//go:nosplit +//go:norace +func sigaltstack(ss *stack_t, old_ss *stack_t) int32 { + return int32(call5(sigaltstackABI0, uintptr(unsafe.Pointer(ss)), uintptr(unsafe.Pointer(old_ss)), 0, 0, 0)) +} + +//go:nosplit +//go:norace +func pthread_attr_init(attr *pthread_attr_t) int32 { + return int32(call5(pthread_attr_initABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0)) +} + +//go:nosplit +//go:norace +func pthread_create(thread *pthread_t, attr *pthread_attr_t, start unsafe.Pointer, arg unsafe.Pointer) int32 { + return int32(call5(pthread_createABI0, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(start), uintptr(arg), 0)) +} + +//go:nosplit +//go:norace +func pthread_detach(thread pthread_t) int32 { + return int32(call5(pthread_detachABI0, uintptr(thread), 0, 0, 0, 0)) +} + +//go:nosplit +//go:norace +func pthread_sigmask(how sighow, ign *sigset_t, oset *sigset_t) int32 { + return int32(call5(pthread_sigmaskABI0, uintptr(how), uintptr(unsafe.Pointer(ign)), uintptr(unsafe.Pointer(oset)), 0, 0)) +} + +//go:nosplit +//go:norace +func pthread_self() pthread_t { + return pthread_t(call5(pthread_selfABI0, 0, 0, 0, 0, 0)) +} + +//go:nosplit +//go:norace +func pthread_get_stacksize_np(thread pthread_t) size_t { + return size_t(call5(pthread_get_stacksize_npABI0, uintptr(thread), 0, 0, 0, 0)) +} + +//go:nosplit +//go:norace +func pthread_attr_getstacksize(attr *pthread_attr_t, stacksize *size_t) int32 { + return int32(call5(pthread_attr_getstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(unsafe.Pointer(stacksize)), 0, 0, 0)) +} + +//go:nosplit +//go:norace +func pthread_attr_setstacksize(attr *pthread_attr_t, size size_t) int32 { + return int32(call5(pthread_attr_setstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(size), 0, 0, 0)) +} + +//go:nosplit +//go:norace +func pthread_attr_destroy(attr *pthread_attr_t) int32 { + return int32(call5(pthread_attr_destroyABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0)) +} + +//go:nosplit +//go:norace +func pthread_mutex_lock(mutex *pthread_mutex_t) int32 { + return int32(call5(pthread_mutex_lockABI0, uintptr(unsafe.Pointer(mutex)), 0, 0, 0, 0)) +} + +//go:nosplit +//go:norace +func pthread_mutex_unlock(mutex *pthread_mutex_t) int32 { + return int32(call5(pthread_mutex_unlockABI0, uintptr(unsafe.Pointer(mutex)), 0, 0, 0, 0)) +} + +//go:nosplit +//go:norace +func pthread_cond_broadcast(cond *pthread_cond_t) int32 { + return int32(call5(pthread_cond_broadcastABI0, uintptr(unsafe.Pointer(cond)), 0, 0, 0, 0)) +} + +//go:nosplit +//go:norace +func pthread_setspecific(key pthread_key_t, value unsafe.Pointer) int32 { + return int32(call5(pthread_setspecificABI0, uintptr(key), uintptr(value), 0, 0, 0)) +} + +//go:linkname _malloc _malloc +var _malloc uint8 +var mallocABI0 = uintptr(unsafe.Pointer(&_malloc)) + +//go:linkname _free _free +var _free uint8 +var freeABI0 = uintptr(unsafe.Pointer(&_free)) + +//go:linkname _setenv _setenv +var _setenv uint8 +var setenvABI0 = uintptr(unsafe.Pointer(&_setenv)) + +//go:linkname _unsetenv _unsetenv +var _unsetenv uint8 +var unsetenvABI0 = uintptr(unsafe.Pointer(&_unsetenv)) + +//go:linkname _sigfillset _sigfillset +var _sigfillset uint8 +var sigfillsetABI0 = uintptr(unsafe.Pointer(&_sigfillset)) + +//go:linkname _nanosleep _nanosleep +var _nanosleep uint8 +var nanosleepABI0 = uintptr(unsafe.Pointer(&_nanosleep)) + +//go:linkname _abort _abort +var _abort uint8 +var abortABI0 = uintptr(unsafe.Pointer(&_abort)) + +//go:linkname _sigaltstack _sigaltstack +var _sigaltstack uint8 +var sigaltstackABI0 = uintptr(unsafe.Pointer(&_sigaltstack)) + +//go:linkname _pthread_attr_init _pthread_attr_init +var _pthread_attr_init uint8 +var pthread_attr_initABI0 = uintptr(unsafe.Pointer(&_pthread_attr_init)) + +//go:linkname _pthread_create _pthread_create +var _pthread_create uint8 +var pthread_createABI0 = uintptr(unsafe.Pointer(&_pthread_create)) + +//go:linkname _pthread_detach _pthread_detach +var _pthread_detach uint8 +var pthread_detachABI0 = uintptr(unsafe.Pointer(&_pthread_detach)) + +//go:linkname _pthread_sigmask _pthread_sigmask +var _pthread_sigmask uint8 +var pthread_sigmaskABI0 = uintptr(unsafe.Pointer(&_pthread_sigmask)) + +//go:linkname _pthread_self _pthread_self +var _pthread_self uint8 +var pthread_selfABI0 = uintptr(unsafe.Pointer(&_pthread_self)) + +//go:linkname _pthread_get_stacksize_np _pthread_get_stacksize_np +var _pthread_get_stacksize_np uint8 +var pthread_get_stacksize_npABI0 = uintptr(unsafe.Pointer(&_pthread_get_stacksize_np)) + +//go:linkname _pthread_attr_getstacksize _pthread_attr_getstacksize +var _pthread_attr_getstacksize uint8 +var pthread_attr_getstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_getstacksize)) + +//go:linkname _pthread_attr_setstacksize _pthread_attr_setstacksize +var _pthread_attr_setstacksize uint8 +var pthread_attr_setstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_setstacksize)) + +//go:linkname _pthread_attr_destroy _pthread_attr_destroy +var _pthread_attr_destroy uint8 +var pthread_attr_destroyABI0 = uintptr(unsafe.Pointer(&_pthread_attr_destroy)) + +//go:linkname _pthread_mutex_lock _pthread_mutex_lock +var _pthread_mutex_lock uint8 +var pthread_mutex_lockABI0 = uintptr(unsafe.Pointer(&_pthread_mutex_lock)) + +//go:linkname _pthread_mutex_unlock _pthread_mutex_unlock +var _pthread_mutex_unlock uint8 +var pthread_mutex_unlockABI0 = uintptr(unsafe.Pointer(&_pthread_mutex_unlock)) + +//go:linkname _pthread_cond_broadcast _pthread_cond_broadcast +var _pthread_cond_broadcast uint8 +var pthread_cond_broadcastABI0 = uintptr(unsafe.Pointer(&_pthread_cond_broadcast)) + +//go:linkname _pthread_setspecific _pthread_setspecific +var _pthread_setspecific uint8 +var pthread_setspecificABI0 = uintptr(unsafe.Pointer(&_pthread_setspecific)) diff --git a/internal/fakecgo/symbols_darwin.go b/internal/fakecgo/symbols_darwin.go new file mode 100644 index 00000000..fa97ae55 --- /dev/null +++ b/internal/fakecgo/symbols_darwin.go @@ -0,0 +1,30 @@ +// Code generated by 'go generate' with gen.go. DO NOT EDIT. + +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2022 The Ebitengine Authors + +//go:build !cgo + +package fakecgo + +//go:cgo_import_dynamic purego_malloc malloc "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic purego_free free "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic purego_setenv setenv "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic purego_unsetenv unsetenv "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic purego_sigfillset sigfillset "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic purego_nanosleep nanosleep "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic purego_abort abort "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic purego_sigaltstack sigaltstack "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic purego_pthread_attr_init pthread_attr_init "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic purego_pthread_create pthread_create "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic purego_pthread_detach pthread_detach "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic purego_pthread_self pthread_self "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic purego_pthread_get_stacksize_np pthread_get_stacksize_np "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic purego_pthread_attr_setstacksize pthread_attr_setstacksize "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "/usr/lib/libSystem.B.dylib" diff --git a/internal/fakecgo/symbols_linux.go b/internal/fakecgo/symbols_linux.go new file mode 100644 index 00000000..dcac8e46 --- /dev/null +++ b/internal/fakecgo/symbols_linux.go @@ -0,0 +1,30 @@ +// Code generated by 'go generate' with gen.go. DO NOT EDIT. + +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2022 The Ebitengine Authors + +//go:build !cgo + +package fakecgo + +//go:cgo_import_dynamic purego_malloc malloc "libc.so.6" +//go:cgo_import_dynamic purego_free free "libc.so.6" +//go:cgo_import_dynamic purego_setenv setenv "libc.so.6" +//go:cgo_import_dynamic purego_unsetenv unsetenv "libc.so.6" +//go:cgo_import_dynamic purego_sigfillset sigfillset "libc.so.6" +//go:cgo_import_dynamic purego_nanosleep nanosleep "libc.so.6" +//go:cgo_import_dynamic purego_abort abort "libc.so.6" +//go:cgo_import_dynamic purego_sigaltstack sigaltstack "libc.so.6" +//go:cgo_import_dynamic purego_pthread_attr_init pthread_attr_init "libpthread.so.0" +//go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so.0" +//go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so.0" +//go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "libpthread.so.0" +//go:cgo_import_dynamic purego_pthread_self pthread_self "libpthread.so.0" +//go:cgo_import_dynamic purego_pthread_get_stacksize_np pthread_get_stacksize_np "libpthread.so.0" +//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so.0" +//go:cgo_import_dynamic purego_pthread_attr_setstacksize pthread_attr_setstacksize "libpthread.so.0" +//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so.0" +//go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "libpthread.so.0" +//go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "libpthread.so.0" +//go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "libpthread.so.0" +//go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "libpthread.so.0" diff --git a/internal/fakecgo/trampolines_amd64.s b/internal/fakecgo/trampolines_amd64.s new file mode 100644 index 00000000..89157868 --- /dev/null +++ b/internal/fakecgo/trampolines_amd64.s @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2022 The Ebitengine Authors + +//go:build !cgo && (darwin || linux) + +/* +trampoline for emulating required C functions for cgo in go (see cgo.go) +(we convert cdecl calling convention to go and vice-versa) + +Since we're called from go and call into C we can cheat a bit with the calling conventions: + - in go all the registers are caller saved + - in C we have a couple of callee saved registers + +=> we can use BX, R12, R13, R14, R15 instead of the stack + +C Calling convention cdecl used here (we only need integer args): +1. arg: DI +2. arg: SI +3. arg: DX +4. arg: CX +5. arg: R8 +6. arg: R9 +We don't need floats with these functions -> AX=0 +return value will be in AX +*/ +#include "textflag.h" +#include "go_asm.h" + +// these trampolines map the gcc ABI to Go ABI and then calls into the Go equivalent functions. + +TEXT x_cgo_init_trampoline(SB), NOSPLIT, $16 + MOVQ DI, AX + MOVQ SI, BX + MOVQ ·x_cgo_init_call(SB), DX + MOVQ (DX), CX + CALL CX + RET + +TEXT x_cgo_thread_start_trampoline(SB), NOSPLIT, $8 + MOVQ DI, AX + MOVQ ·x_cgo_thread_start_call(SB), DX + MOVQ (DX), CX + CALL CX + RET + +TEXT x_cgo_setenv_trampoline(SB), NOSPLIT, $8 + MOVQ DI, AX + MOVQ ·x_cgo_setenv_call(SB), DX + MOVQ (DX), CX + CALL CX + RET + +TEXT x_cgo_unsetenv_trampoline(SB), NOSPLIT, $8 + MOVQ DI, AX + MOVQ ·x_cgo_unsetenv_call(SB), DX + MOVQ (DX), CX + CALL CX + RET + +TEXT x_cgo_notify_runtime_init_done_trampoline(SB), NOSPLIT, $0 + CALL ·x_cgo_notify_runtime_init_done(SB) + RET + +TEXT x_cgo_bindm_trampoline(SB), NOSPLIT, $0 + CALL ·x_cgo_bindm(SB) + RET + +// func setg_trampoline(setg uintptr, g uintptr) +TEXT ·setg_trampoline(SB), NOSPLIT, $0-16 + MOVQ G+8(FP), DI + MOVQ setg+0(FP), BX + XORL AX, AX + CALL BX + RET + +TEXT threadentry_trampoline(SB), NOSPLIT, $16 + MOVQ DI, AX + MOVQ ·threadentry_call(SB), DX + MOVQ (DX), CX + CALL CX + RET + +TEXT ·call5(SB), NOSPLIT, $0-56 + MOVQ fn+0(FP), BX + MOVQ a1+8(FP), DI + MOVQ a2+16(FP), SI + MOVQ a3+24(FP), DX + MOVQ a4+32(FP), CX + MOVQ a5+40(FP), R8 + + XORL AX, AX // no floats + + PUSHQ BP // save BP + MOVQ SP, BP // save SP inside BP bc BP is callee-saved + SUBQ $16, SP // allocate space for alignment + ANDQ $-16, SP // align on 16 bytes for SSE + + CALL BX + + MOVQ BP, SP // get SP back + POPQ BP // restore BP + + MOVQ AX, ret+48(FP) + RET diff --git a/internal/fakecgo/trampolines_arm64.s b/internal/fakecgo/trampolines_arm64.s new file mode 100644 index 00000000..46987d71 --- /dev/null +++ b/internal/fakecgo/trampolines_arm64.s @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2022 The Ebitengine Authors + +//go:build !cgo && (darwin || linux) + +#include "textflag.h" +#include "go_asm.h" + +// these trampolines map the gcc ABI to Go ABI and then calls into the Go equivalent functions. + +TEXT x_cgo_init_trampoline(SB), NOSPLIT, $0-0 + MOVD R0, 8(RSP) + MOVD R1, 16(RSP) + MOVD ·x_cgo_init_call(SB), R26 + MOVD (R26), R2 + CALL (R2) + RET + +TEXT x_cgo_thread_start_trampoline(SB), NOSPLIT, $0-0 + MOVD R0, 8(RSP) + MOVD ·x_cgo_thread_start_call(SB), R26 + MOVD (R26), R2 + CALL (R2) + RET + +TEXT x_cgo_setenv_trampoline(SB), NOSPLIT, $0-0 + MOVD R0, 8(RSP) + MOVD ·x_cgo_setenv_call(SB), R26 + MOVD (R26), R2 + CALL (R2) + RET + +TEXT x_cgo_unsetenv_trampoline(SB), NOSPLIT, $0-0 + MOVD R0, 8(RSP) + MOVD ·x_cgo_unsetenv_call(SB), R26 + MOVD (R26), R2 + CALL (R2) + RET + +TEXT x_cgo_notify_runtime_init_done_trampoline(SB), NOSPLIT, $0-0 + CALL ·x_cgo_notify_runtime_init_done(SB) + RET + +TEXT x_cgo_bindm_trampoline(SB), NOSPLIT, $0 + CALL ·x_cgo_bindm(SB) + RET + +// func setg_trampoline(setg uintptr, g uintptr) +TEXT ·setg_trampoline(SB), NOSPLIT, $0-16 + MOVD G+8(FP), R0 + MOVD setg+0(FP), R1 + CALL R1 + RET + +TEXT threadentry_trampoline(SB), NOSPLIT, $0-0 + MOVD R0, 8(RSP) + MOVD ·threadentry_call(SB), R26 + MOVD (R26), R2 + CALL (R2) + MOVD $0, R0 // TODO: get the return value from threadentry + RET + +TEXT ·call5(SB), NOSPLIT, $0-0 + MOVD fn+0(FP), R6 + MOVD a1+8(FP), R0 + MOVD a2+16(FP), R1 + MOVD a3+24(FP), R2 + MOVD a4+32(FP), R3 + MOVD a5+40(FP), R4 + CALL R6 + MOVD R0, ret+48(FP) + RET diff --git a/internal/fakecgo/trampolines_stubs.s b/internal/fakecgo/trampolines_stubs.s new file mode 100644 index 00000000..3cb26f4d --- /dev/null +++ b/internal/fakecgo/trampolines_stubs.s @@ -0,0 +1,94 @@ +// Code generated by 'go generate' with gen.go. DO NOT EDIT. + +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2022 The Ebitengine Authors + +//go:build !cgo && (darwin || linux) + +#include "textflag.h" + +// these stubs are here because it is not possible to go:linkname directly the C functions on darwin arm64 + +TEXT _malloc(SB), NOSPLIT|NOFRAME, $0-0 + JMP purego_malloc(SB) + RET + +TEXT _free(SB), NOSPLIT|NOFRAME, $0-0 + JMP purego_free(SB) + RET + +TEXT _setenv(SB), NOSPLIT|NOFRAME, $0-0 + JMP purego_setenv(SB) + RET + +TEXT _unsetenv(SB), NOSPLIT|NOFRAME, $0-0 + JMP purego_unsetenv(SB) + RET + +TEXT _sigfillset(SB), NOSPLIT|NOFRAME, $0-0 + JMP purego_sigfillset(SB) + RET + +TEXT _nanosleep(SB), NOSPLIT|NOFRAME, $0-0 + JMP purego_nanosleep(SB) + RET + +TEXT _abort(SB), NOSPLIT|NOFRAME, $0-0 + JMP purego_abort(SB) + RET + +TEXT _sigaltstack(SB), NOSPLIT|NOFRAME, $0-0 + JMP purego_sigaltstack(SB) + RET + +TEXT _pthread_attr_init(SB), NOSPLIT|NOFRAME, $0-0 + JMP purego_pthread_attr_init(SB) + RET + +TEXT _pthread_create(SB), NOSPLIT|NOFRAME, $0-0 + JMP purego_pthread_create(SB) + RET + +TEXT _pthread_detach(SB), NOSPLIT|NOFRAME, $0-0 + JMP purego_pthread_detach(SB) + RET + +TEXT _pthread_sigmask(SB), NOSPLIT|NOFRAME, $0-0 + JMP purego_pthread_sigmask(SB) + RET + +TEXT _pthread_self(SB), NOSPLIT|NOFRAME, $0-0 + JMP purego_pthread_self(SB) + RET + +TEXT _pthread_get_stacksize_np(SB), NOSPLIT|NOFRAME, $0-0 + JMP purego_pthread_get_stacksize_np(SB) + RET + +TEXT _pthread_attr_getstacksize(SB), NOSPLIT|NOFRAME, $0-0 + JMP purego_pthread_attr_getstacksize(SB) + RET + +TEXT _pthread_attr_setstacksize(SB), NOSPLIT|NOFRAME, $0-0 + JMP purego_pthread_attr_setstacksize(SB) + RET + +TEXT _pthread_attr_destroy(SB), NOSPLIT|NOFRAME, $0-0 + JMP purego_pthread_attr_destroy(SB) + RET + +TEXT _pthread_mutex_lock(SB), NOSPLIT|NOFRAME, $0-0 + JMP purego_pthread_mutex_lock(SB) + RET + +TEXT _pthread_mutex_unlock(SB), NOSPLIT|NOFRAME, $0-0 + JMP purego_pthread_mutex_unlock(SB) + RET + +TEXT _pthread_cond_broadcast(SB), NOSPLIT|NOFRAME, $0-0 + JMP purego_pthread_cond_broadcast(SB) + RET + +TEXT _pthread_setspecific(SB), NOSPLIT|NOFRAME, $0-0 + JMP purego_pthread_setspecific(SB) + RET diff --git a/internal/mkcgo/mkcgo.go b/internal/mkcgo/mkcgo.go index deddfcef..ca956a34 100644 --- a/internal/mkcgo/mkcgo.go +++ b/internal/mkcgo/mkcgo.go @@ -12,6 +12,7 @@ import ( // Source is a collection of type definitions and functions. type Source struct { TypeDefs []*TypeDef + Externs []*Extern Enums []*Enum Funcs []*Func Comments []string // All line comments. Leading and trailing spaces are trimmed. @@ -26,14 +27,34 @@ type TypeDef struct { Type string } -// Enum describes an enum definition. +// Extern describes an extern variable. +type Extern struct { + Name string + Type string + Framework Framework + Static bool +} + +// Enum describes an enum block. type Enum struct { + Type string + Values []EnumValue +} + +// EnumValue describes an enum definition. +type EnumValue struct { Name string Value string } -// FuncAttrs contains attributes of a function. -type FuncAttrs struct { +// Framework describes a framework +type Framework struct { + Name string + Version string +} + +// Attrs contains attributes of a C symbol. +type Attrs struct { Tags []TagAttr VariadicTarget string Optional bool @@ -42,9 +63,11 @@ type FuncAttrs struct { NoEscape bool NoCallback bool NoCheckPtrParams []string + Framework Framework + Static bool } -func (attrs *FuncAttrs) String() string { +func (attrs *Attrs) String() string { var bld strings.Builder if len(attrs.Tags) != 0 { bld.Write([]byte(fmt.Sprintf("%s", attrs.Tags))) @@ -81,12 +104,19 @@ func (attrs *FuncAttrs) String() string { } bld.WriteByte(')') } + if len(attrs.Framework.Name) != 0 { + bld.WriteString(", framework(") + bld.WriteString(attrs.Framework.Name) + bld.WriteString(", ") + bld.WriteString(attrs.Framework.Version) + bld.WriteByte(')') + } return strings.TrimPrefix(bld.String(), ", ") } // Func describes a function. type Func struct { - FuncAttrs + Attrs Name string Params []*Param Ret string @@ -126,7 +156,7 @@ func (f *Func) String() string { } } bld.WriteString(")") - if attrs := f.FuncAttrs.String(); attrs != "" { + if attrs := f.Attrs.String(); attrs != "" { bld.WriteByte(' ') bld.WriteString(attrs) } @@ -172,14 +202,14 @@ func (src *Source) Tags() []string { type attribute struct { name string description string - handle func(*FuncAttrs, ...string) error + handle func(*Attrs, ...string) error } var attributes = [...]attribute{ { name: "tag", description: "The function will be loaded together with other functions with the same tag. It can contain an optional name, which is the import name for the tag.", - handle: func(opts *FuncAttrs, s ...string) error { + handle: func(opts *Attrs, s ...string) error { var name string if len(s) > 1 { name = s[1] @@ -191,7 +221,7 @@ var attributes = [...]attribute{ { name: "variadic", description: "The function has variadic arguments, and its name is a custom wrapper for the actual C name, defined in this attribute.", - handle: func(opts *FuncAttrs, s ...string) error { + handle: func(opts *Attrs, s ...string) error { opts.VariadicTarget = s[0] return nil }, @@ -199,7 +229,7 @@ var attributes = [...]attribute{ { name: "optional", description: "The function is optional", - handle: func(opts *FuncAttrs, s ...string) error { + handle: func(opts *Attrs, s ...string) error { opts.Optional = true return nil }, @@ -207,7 +237,7 @@ var attributes = [...]attribute{ { name: "noerror", description: "The function does not return an error, and the program will panic if the function returns an error.", - handle: func(opts *FuncAttrs, s ...string) error { + handle: func(opts *Attrs, s ...string) error { if opts.ErrCond != "" { return errors.New("not allowed with errcond attribute") } @@ -218,7 +248,7 @@ var attributes = [...]attribute{ { name: "errcond", description: "The function returns an error if the C function returns a value that matches the condition in this attribute.", - handle: func(opts *FuncAttrs, s ...string) error { + handle: func(opts *Attrs, s ...string) error { if opts.NoError { return errors.New("not allowed with noerror attribute") } @@ -229,7 +259,7 @@ var attributes = [...]attribute{ { name: "noescape", description: "The C function does not keep a copy of the Go pointer.", - handle: func(opts *FuncAttrs, s ...string) error { + handle: func(opts *Attrs, s ...string) error { opts.NoEscape = true return nil }, @@ -237,7 +267,7 @@ var attributes = [...]attribute{ { name: "nocallback", description: "The C function does not call back into Go.", - handle: func(opts *FuncAttrs, s ...string) error { + handle: func(opts *Attrs, s ...string) error { opts.NoCallback = true return nil }, @@ -245,9 +275,28 @@ var attributes = [...]attribute{ { name: "nocheckptr", description: "The parameter will be hidden from the Go compiler.", - handle: func(opts *FuncAttrs, s ...string) error { + handle: func(opts *Attrs, s ...string) error { opts.NoCheckPtrParams = append(opts.NoCheckPtrParams, s[0]) return nil }, }, + { + name: "static", + description: "Use static cgo import for this symbol.", + handle: func(opts *Attrs, s ...string) error { + opts.Static = true + return nil + }, + }, + { + name: "framework", + description: "The function is part of a framework.", + handle: func(opts *Attrs, s ...string) error { + if len(s) != 2 { + return errors.New("requires 2 arguments") + } + opts.Framework = Framework{Name: s[0], Version: s[1]} + return nil + }, + }, } diff --git a/internal/mkcgo/mkcgo_test.go b/internal/mkcgo/mkcgo_test.go index fb773ec0..53bc2e51 100644 --- a/internal/mkcgo/mkcgo_test.go +++ b/internal/mkcgo/mkcgo_test.go @@ -71,32 +71,32 @@ func TestSourceTags(t *testing.T) { { name: "Functions with no tags", funcs: []*mkcgo.Func{ - {Name: "Func1", FuncAttrs: mkcgo.FuncAttrs{Tags: []mkcgo.TagAttr{}}}, - {Name: "Func2", FuncAttrs: mkcgo.FuncAttrs{Tags: []mkcgo.TagAttr{}}}, + {Name: "Func1", Attrs: mkcgo.Attrs{Tags: []mkcgo.TagAttr{}}}, + {Name: "Func2", Attrs: mkcgo.Attrs{Tags: []mkcgo.TagAttr{}}}, }, want: []string{""}, }, { name: "Functions with unique tags", funcs: []*mkcgo.Func{ - {Name: "Func1", FuncAttrs: mkcgo.FuncAttrs{Tags: []mkcgo.TagAttr{{Tag: "tag1"}}}}, - {Name: "Func2", FuncAttrs: mkcgo.FuncAttrs{Tags: []mkcgo.TagAttr{{Tag: "tag2"}}}}, + {Name: "Func1", Attrs: mkcgo.Attrs{Tags: []mkcgo.TagAttr{{Tag: "tag1"}}}}, + {Name: "Func2", Attrs: mkcgo.Attrs{Tags: []mkcgo.TagAttr{{Tag: "tag2"}}}}, }, want: []string{"", "tag1", "tag2"}, }, { name: "Functions with duplicate tags", funcs: []*mkcgo.Func{ - {Name: "Func1", FuncAttrs: mkcgo.FuncAttrs{Tags: []mkcgo.TagAttr{{Tag: "tag1"}}}}, - {Name: "Func2", FuncAttrs: mkcgo.FuncAttrs{Tags: []mkcgo.TagAttr{{Tag: "tag1"}, {Tag: "tag2"}}}}, + {Name: "Func1", Attrs: mkcgo.Attrs{Tags: []mkcgo.TagAttr{{Tag: "tag1"}}}}, + {Name: "Func2", Attrs: mkcgo.Attrs{Tags: []mkcgo.TagAttr{{Tag: "tag1"}, {Tag: "tag2"}}}}, }, want: []string{"", "tag1", "tag2"}, }, { name: "Functions with unsorted tags", funcs: []*mkcgo.Func{ - {Name: "Func1", FuncAttrs: mkcgo.FuncAttrs{Tags: []mkcgo.TagAttr{{Tag: "tag3"}}}}, - {Name: "Func2", FuncAttrs: mkcgo.FuncAttrs{Tags: []mkcgo.TagAttr{{Tag: "tag1"}, {Tag: "tag2"}}}}, + {Name: "Func1", Attrs: mkcgo.Attrs{Tags: []mkcgo.TagAttr{{Tag: "tag3"}}}}, + {Name: "Func2", Attrs: mkcgo.Attrs{Tags: []mkcgo.TagAttr{{Tag: "tag1"}, {Tag: "tag2"}}}}, }, want: []string{"", "tag1", "tag2", "tag3"}, }, @@ -137,8 +137,8 @@ func TestFuncImportName(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { fn := &mkcgo.Func{ - FuncAttrs: mkcgo.FuncAttrs{VariadicTarget: tt.variadicTarget}, - Name: tt.funcName, + Attrs: mkcgo.Attrs{VariadicTarget: tt.variadicTarget}, + Name: tt.funcName, } if got := fn.ImportName(); got != tt.want { t.Errorf("Func.ImportName() = %v, want %v", got, tt.want) @@ -176,7 +176,7 @@ func TestFuncString(t *testing.T) { { name: "Function with attributes", function: &mkcgo.Func{Name: "TestFunc", Ret: "void", Params: []*mkcgo.Param{{Type: "int", Name: "param1"}}, - FuncAttrs: mkcgo.FuncAttrs{ + Attrs: mkcgo.Attrs{ Tags: []mkcgo.TagAttr{{Tag: "tag1"}, {Tag: "tag2", Name: "name"}}, Optional: true, NoError: true, @@ -184,9 +184,10 @@ func TestFuncString(t *testing.T) { NoEscape: true, NoCallback: true, NoCheckPtrParams: []string{"param1"}, + Framework: mkcgo.Framework{Name: "CoreFoundation", Version: "A"}, }, }, - want: "void TestFunc(int param1) [{tag1 } {tag2 name}], optional, noerror, errcond(error_condition), noescape, nocallback, nocheckptr(param1)", + want: "void TestFunc(int param1) [{tag1 } {tag2 name}], optional, noerror, errcond(error_condition), noescape, nocallback, nocheckptr(param1), framework(CoreFoundation, A)", }, } @@ -240,9 +241,13 @@ enum { };`, want: &mkcgo.Source{ Enums: []*mkcgo.Enum{ - {"E0", "1"}, - {"E1", "(1+1)"}, - {"E2", "(1+2)"}, + { + Values: []mkcgo.EnumValue{ + {"E0", "1"}, + {"E1", "(1+1)"}, + {"E2", "(1+2)"}, + }, + }, }, }, }, { @@ -256,12 +261,12 @@ int* F5(float, double) __attribute__((variadic("F4"))); void F6() __attribute__(());`, want: &mkcgo.Source{ Funcs: []*mkcgo.Func{ - {Name: "F0", Ret: "void", Params: []*mkcgo.Param{{"void", ""}}, FuncAttrs: mkcgo.FuncAttrs{Tags: []mkcgo.TagAttr{{Tag: "t0"}, {Tag: "t1", Name: "tn0"}}, NoError: true}}, - {Name: "F1", Ret: "int", Params: []*mkcgo.Param{{"int", "p1"}}, FuncAttrs: mkcgo.FuncAttrs{ErrCond: "ec0", NoEscape: true, NoCallback: true, NoCheckPtrParams: []string{"p1"}}}, + {Name: "F0", Ret: "void", Params: []*mkcgo.Param{{"void", ""}}, Attrs: mkcgo.Attrs{Tags: []mkcgo.TagAttr{{Tag: "t0"}, {Tag: "t1", Name: "tn0"}}, NoError: true}}, + {Name: "F1", Ret: "int", Params: []*mkcgo.Param{{"int", "p1"}}, Attrs: mkcgo.Attrs{ErrCond: "ec0", NoEscape: true, NoCallback: true, NoCheckPtrParams: []string{"p1"}}}, {Name: "F2", Ret: "int*", Params: []*mkcgo.Param{{"int**", "p1"}, {"void*", "p2"}}}, - {Name: "F3", Ret: "int*", Params: []*mkcgo.Param{{"int", "p1"}, {"void***", ""}}, FuncAttrs: mkcgo.FuncAttrs{Optional: true}}, + {Name: "F3", Ret: "int*", Params: []*mkcgo.Param{{"int", "p1"}, {"void***", ""}}, Attrs: mkcgo.Attrs{Optional: true}}, {Name: "F4", Ret: "unsigned long", Params: []*mkcgo.Param{{"int", "__func"}, {"int", "__type"}, {"...", ""}}}, - {Name: "F5", Ret: "int*", Params: []*mkcgo.Param{{"float", ""}, {"double", ""}}, FuncAttrs: mkcgo.FuncAttrs{VariadicTarget: "F4"}}, + {Name: "F5", Ret: "int*", Params: []*mkcgo.Param{{"float", ""}, {"double", ""}}, Attrs: mkcgo.Attrs{VariadicTarget: "F4"}}, {Name: "F6", Ret: "void", Params: []*mkcgo.Param{{"void", ""}}}, }, }, @@ -362,6 +367,11 @@ typedef void* E2; void E2(void); `, want: `duplicate symbol "E2"`, + }, { + content: ` +void F1(void) __attribute__((framework("t1"))); +`, + want: `can't extract function attributes: error parsing attribute framework: requires 2 arguments`, }, } for i, tt := range tests { diff --git a/internal/mkcgo/parse.go b/internal/mkcgo/parse.go index 7723bc51..6492749e 100644 --- a/internal/mkcgo/parse.go +++ b/internal/mkcgo/parse.go @@ -4,6 +4,7 @@ import ( "bufio" "errors" "fmt" + "go/token" "io" "slices" "strings" @@ -35,12 +36,24 @@ func (src *Source) Parse(r io.Reader) error { inEnum = false continue } + if line, found := strings.CutPrefix(line, "} "); found { + typeName := strings.TrimSuffix(line, ";") + typeName, _ = normalizeParam(typeName, "") + if err := src.addSymbol(typeName); err != nil { + return err + } + enum := src.Enums[len(src.Enums)-1] + enum.Type = typeName + inEnum = false + continue + } if err := src.addEnum(line); err != nil { return fmt.Errorf("can't parse enum in line %q: %w", line, err) } continue } - if strings.HasPrefix(line, "enum {") { + if strings.HasPrefix(line, "enum {") || strings.HasPrefix(line, "typedef enum {") { + src.Enums = append(src.Enums, &Enum{}) inEnum = true continue } @@ -62,6 +75,14 @@ func (src *Source) Parse(r io.Reader) error { continue } + // Process extern variables. + if v, found := strings.CutPrefix(line, "extern "); found { + if err := src.addExtern(v); err != nil { + return fmt.Errorf("can't parse extern in line %q: %w", line, err) + } + continue + } + // Process function. if err := src.addFn(line); err != nil { return fmt.Errorf("can't parse function in line %q: %w", line, err) @@ -92,7 +113,8 @@ func (src *Source) addEnum(line string) error { if err := src.addSymbol(name); err != nil { return err } - src.Enums = append(src.Enums, &Enum{ + enum := src.Enums[len(src.Enums)-1] + enum.Values = append(enum.Values, EnumValue{ Name: name, Value: value, }) @@ -118,11 +140,36 @@ func (src *Source) addTypeDef(line string) error { return nil } +func (src *Source) addExtern(line string) error { + line = strings.TrimSuffix(line, ";") + var attrs Attrs + var err error + line, err = extractAttributes(line, &attrs) + if err != nil { + return fmt.Errorf("can't extract extern attributes: %w", err) + } + idx := strings.LastIndex(line, " ") + if idx < 0 { + return errors.New("can't extract type name") + } + name, typ := normalizeParam(line[idx+1:], line[:idx]) + if err := src.addSymbol(name); err != nil { + return err + } + src.Externs = append(src.Externs, &Extern{ + Name: name, + Type: typ, + Framework: attrs.Framework, + Static: attrs.Static, + }) + return nil +} + // addFn parses string s and return created function Fn. func (src *Source) addFn(s string) error { s = strings.TrimSuffix(s, ";") - var attrs FuncAttrs - s, err := extractFunctionAttributes(s, &attrs) + var attrs Attrs + s, err := extractAttributes(s, &attrs) if err != nil { return fmt.Errorf("can't extract function attributes: %w", err) } @@ -159,10 +206,10 @@ func (src *Source) addFn(s string) error { return err } src.Funcs = append(src.Funcs, &Func{ - Name: name, - Ret: ret, - FuncAttrs: attrs, - Params: params, + Name: name, + Ret: ret, + Attrs: attrs, + Params: params, }) return nil } @@ -175,8 +222,7 @@ func normalizeParam(name, typ string) (string, string) { name = name[1:] typ += "*" } - switch name { - case "type", "func": + if token.IsKeyword(name) || name == "error" { name = "__" + name } // Remove duplicated spaces. @@ -245,10 +291,10 @@ func processComments(line string) (comment, remmaining string) { return "", line } -// extractFunctionAttributes extracts mkcgo attributes from string s. +// extractAttributes extracts mkcgo attributes from string s. // The attributes format follows the GCC __attribute__ syntax as // described in https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html. -func extractFunctionAttributes(s string, fnAttrs *FuncAttrs) (string, error) { +func extractAttributes(s string, fnAttrs *Attrs) (string, error) { // There can be spaces between __attribute__ and the opening parenthesis. prefix, body, found := strings.Cut(s, "__attribute__") if !found { diff --git a/internal/ossl/asm_amd64.s b/internal/ossl/asm_amd64.s new file mode 100644 index 00000000..716fecf3 --- /dev/null +++ b/internal/ossl/asm_amd64.s @@ -0,0 +1,73 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !cgo && unix + +#include "go_asm.h" +#include "textflag.h" + +GLOBL ·syscallNABI0(SB), NOPTR|RODATA, $8 +DATA ·syscallNABI0(SB)/8, $syscallN_trampoline(SB) +TEXT syscallN_trampoline(SB),NOSPLIT,$0 + // store argument and original SP in a callee-saved register + MOVQ DI, R13 + MOVQ SP, R14 + + MOVQ libcCallInfo_fn(R13), R11 + MOVQ libcCallInfo_n(R13), CX + MOVQ libcCallInfo_args(R13), R10 + + // Fast version, do not store args on the stack. + CMPL CX, $0; JE _0args + CMPL CX, $1; JE _1args + CMPL CX, $2; JE _2args + CMPL CX, $3; JE _3args + CMPL CX, $4; JE _4args + CMPL CX, $5; JE _5args + CMPL CX, $6; JE _6args + + // Reserve stack space for remaining args + MOVQ CX, R12 + SUBQ $6, R12 + ADDQ $1, R12 // make even number of words for stack alignment + ANDQ $~1, R12 + SHLQ $3, R12 + SUBQ R12, SP + + // Copy args to the stack. + // CX: count of stack arguments (n-6) + // SI: &args[6] + // DI: copy of RSP + SUBQ $6, CX + MOVQ R10, SI + ADDQ $(8*6), SI + MOVQ SP, DI + CLD + REP; MOVSQ + +_6args: + MOVQ (5*8)(R10), R9 +_5args: + MOVQ (4*8)(R10), R8 +_4args: + MOVQ (3*8)(R10), CX +_3args: + MOVQ (2*8)(R10), DX +_2args: + MOVQ (1*8)(R10), SI +_1args: + MOVQ (0*8)(R10), DI +_0args: + + XORL AX, AX // vararg: say "no float args" + + CALL R11 + + MOVQ R14, SP // free stack space + + // Return result. + MOVQ AX, libcCallInfo_r1(R13) + MOVQ DX, libcCallInfo_r2(R13) + + RET diff --git a/internal/ossl/asm_arm64.s b/internal/ossl/asm_arm64.s new file mode 100644 index 00000000..ddfe21f0 --- /dev/null +++ b/internal/ossl/asm_arm64.s @@ -0,0 +1,83 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !cgo && unix + +#include "go_asm.h" +#include "textflag.h" + +GLOBL ·syscallNABI0(SB), NOPTR|RODATA, $8 +DATA ·syscallNABI0(SB)/8, $syscallN_trampoline(SB) +TEXT syscallN_trampoline(SB),NOSPLIT,$0 + STP (R19, R20), 16(RSP) // save old R19, R20 + MOVD R0, R19 // save struct pointer + MOVD RSP, R20 // save stack pointer + SUB $16, RSP // reserve 16 bytes for sp-8 where fp may be saved. + + MOVD libcCallInfo_args(R19), R12 + // Do we have more than 8 arguments? + MOVD libcCallInfo_n(R19), R0 + CMP $0, R0; BEQ _0args + CMP $1, R0; BEQ _1args + CMP $2, R0; BEQ _2args + CMP $3, R0; BEQ _3args + CMP $4, R0; BEQ _4args + CMP $5, R0; BEQ _5args + CMP $6, R0; BEQ _6args + CMP $7, R0; BEQ _7args + CMP $8, R0; BEQ _8args + + // Reserve stack space for remaining args + SUB $8, R0, R2 + ADD $1, R2, R3 // make even number of words for stack alignment + AND $~1, R3 + LSL $3, R3 + SUB R3, RSP + + // R4: size of stack arguments (n-8)*8 + // R5: &args[8] + // R6: loop counter, from 0 to (n-8)*8 + // R7: scratch + // R8: copy of RSP - (R2)(RSP) assembles as (R2)(ZR) + SUB $8, R0, R4 + LSL $3, R4 + ADD $(8*8), R12, R5 + MOVD $0, R6 + MOVD RSP, R8 +stackargs: + MOVD (R6)(R5), R7 + MOVD R7, (R6)(R8) + ADD $8, R6 + CMP R6, R4 + BNE stackargs + +_8args: + MOVD (7*8)(R12), R7 +_7args: + MOVD (6*8)(R12), R6 +_6args: + MOVD (5*8)(R12), R5 +_5args: + MOVD (4*8)(R12), R4 +_4args: + MOVD (3*8)(R12), R3 +_3args: + MOVD (2*8)(R12), R2 +_2args: + MOVD (1*8)(R12), R1 +_1args: + MOVD (0*8)(R12), R0 +_0args: + + MOVD libcCallInfo_fn(R19), R12 + BL (R12) + + MOVD R20, RSP // free stack space + + MOVD R0, libcCallInfo_r1(R19) // save r1 + MOVD R1, libcCallInfo_r2(R19) // save r2 + + // Restore callee-saved registers. + LDP 16(RSP), (R19, R20) + RET diff --git a/internal/ossl/dl.h b/internal/ossl/dl.h new file mode 100644 index 00000000..e94cca9e --- /dev/null +++ b/internal/ossl/dl.h @@ -0,0 +1,12 @@ +// This header file is used by the mkcgo tool to generate cgo and Go bindings for the +// OpenSSL C API. Run "go generate ." to regenerate the bindings. + +#ifndef _GO_DL_SHIMS_H // only include this header once +#define _GO_DL_SHIMS_H + +void *dlopen(const char *path, int flags); +int dlclose(void *handle); +void *dlsym(void *handle, const char *symbol); +char *dlerror(void); + +#endif // _GO_DL_SHIMS_H diff --git a/internal/ossl/errors.go b/internal/ossl/errors_cgo.go similarity index 99% rename from internal/ossl/errors.go rename to internal/ossl/errors_cgo.go index 284952ca..3c5df13e 100644 --- a/internal/ossl/errors.go +++ b/internal/ossl/errors_cgo.go @@ -87,7 +87,7 @@ func newMkcgoErr(msg string, errst C.mkcgo_err_state) error { b.WriteString(msg) b.WriteString("\nopenssl error(s):") for i := range C.ERR_NUM_MAX { - e := uint32(oerrst.code[i]) + e := uint64(oerrst.code[i]) if e == 0 { break } diff --git a/internal/ossl/errors_nocgo.go b/internal/ossl/errors_nocgo.go new file mode 100644 index 00000000..c8dd1563 --- /dev/null +++ b/internal/ossl/errors_nocgo.go @@ -0,0 +1,98 @@ +//go:build !cgo + +package ossl + +import ( + "bytes" + "errors" + "strconv" + "strings" + "unsafe" +) + +const ERR_NUM_MAX = 16 + +// errState represents the OpenSSL error state for nocgo version +type errState struct { + codes []uint64 + files []string + lines []int32 +} + +// retrieveErrorState retrieves errors from the OpenSSL error queue +func retrieveErrorState() *errState { + state := &errState{ + codes: make([]uint64, 0, ERR_NUM_MAX), + files: make([]string, 0, ERR_NUM_MAX), + lines: make([]int32, 0, ERR_NUM_MAX), + } + + for range ERR_NUM_MAX { + var file *byte + var line int32 + + var code uint64 + if OPENSSL_version_major_Available() && OPENSSL_version_major() >= 3 { + // OpenSSL 3 error handling + code = ERR_get_error_all(&file, &line, nil, nil, nil) + } else { + // OpenSSL 1 error handling + code = ERR_get_error_line(&file, &line) + } + + if code == 0 { + break + } + + state.codes = append(state.codes, code) + state.lines = append(state.lines, line) + + if file != nil { + // Convert C string to Go string + filename := goString(file) + state.files = append(state.files, filename) + } else { + state.files = append(state.files, "") + } + } + + return state +} + +// newMkcgoErr creates a new error from OpenSSL error queue for nocgo version +// The errst parameter is ignored in nocgo mode, errors are retrieved directly from OpenSSL +func newMkcgoErr(msg string, errst interface{}) error { + // Retrieve error state from OpenSSL error queue + state := retrieveErrorState() + + // If no errors in queue, return simple message + if len(state.codes) == 0 { + return errors.New(msg + " failed") + } + + var b strings.Builder + b.WriteString(msg) + b.WriteString("\nopenssl error(s):") + + for i, code := range state.codes { + b.WriteByte('\n') + var buf [256]byte + ERR_error_string_n(code, unsafe.SliceData(buf[:]), len(buf)) + if termIdx := bytes.IndexByte(buf[:], 0); termIdx != -1 { + b.Write(buf[:termIdx]) + } else { + b.Write(buf[:]) + } + + if i < len(state.files) && state.files[i] != "" { + b.WriteString("\n\t") + b.WriteString(state.files[i]) + b.WriteByte(':') + if i < len(state.lines) { + b.WriteString(strconv.Itoa(int(state.lines[i]))) + } + } + } + + return errors.New(b.String()) +} diff --git a/internal/ossl/ossl.go b/internal/ossl/ossl.go index e0d0b8e8..9d38464e 100644 --- a/internal/ossl/ossl.go +++ b/internal/ossl/ossl.go @@ -1,45 +1,11 @@ // Package ossl provides a Go interface to OpenSSL. package ossl -//go:generate go run ../../cmd/mkcgo -out zossl.go -package ossl shims.h +//go:generate go run ../../cmd/mkcgo -out zossl.go -mode dynload -package ossl shims.h +//go:generate go run ../../cmd/mkcgo -out zossl.go -nocgo -mode dynload -package ossl shims.h +//go:generate go run ../../cmd/mkcgo -out zdl.go -nocgo -mode dynamic -noerrors -package ossl -tags unix dl.h -/* -#include "zossl.h" -// go_hash_sum copies ctx into ctx2 and calls EVP_DigestFinal_ex using ctx2. -// This is necessary because Go hash.Hash mandates that Sum has no effect -// on the underlying stream. In particular it is OK to Sum, then Write more, -// then Sum again, and the second Sum acts as if the first didn't happen. -// It is written in C because Sum() tend to be in the hot path, -// and doing one cgo call instead of two is a significant performance win. -static inline int -go_hash_sum(const _EVP_MD_CTX_PTR ctx, _EVP_MD_CTX_PTR ctx2, unsigned char *out, mkcgo_err_state *_err_state) -{ - if (_mkcgo_EVP_MD_CTX_copy(ctx2, ctx, _err_state) != 1) - return -1; - if (_mkcgo_EVP_DigestFinal_ex(ctx2, out, NULL, _err_state) <= 0) - return -2; - return 1; -} -*/ -import "C" -import ( - "unsafe" -) - -func HashSum(ctx1, ctx2 EVP_MD_CTX_PTR, out []byte) error { - var errst C.mkcgo_err_state - if code := C.go_hash_sum(ctx1, ctx2, (*C.uchar)(unsafe.SliceData(out)), mkcgoNoEscape(&errst)); code != 1 { - msg := "go_hash_sum" - switch code { - case -1: - msg = "EVP_MD_CTX_copy" - case -2: - msg = "EVP_DigestFinal_ex" - } - return newMkcgoErr(msg, errst) - } - return nil -} +import "unsafe" const _OSSL_PARAM_UNMODIFIED uint = uint(^uintptr(0)) @@ -79,3 +45,15 @@ func OSSL_PARAM_modified(param *OSSL_PARAM) bool { // If ReturnSize is not set, the parameter has not been modified. return param != nil && param.ReturnSize != _OSSL_PARAM_UNMODIFIED } + +// goString converts a C string (byte pointer) to a Go string +func goString(p *byte) string { + if p == nil { + return "" + } + end := unsafe.Pointer(p) + for *(*byte)(end) != 0 { + end = unsafe.Add(end, 1) + } + return string(unsafe.Slice(p, uintptr(end)-uintptr(unsafe.Pointer(p)))) +} diff --git a/internal/ossl/ossl_cgo.go b/internal/ossl/ossl_cgo.go new file mode 100644 index 00000000..5fb8d79a --- /dev/null +++ b/internal/ossl/ossl_cgo.go @@ -0,0 +1,39 @@ +package ossl + +/* +#include "zossl.h" +// go_hash_sum copies ctx into ctx2 and calls EVP_DigestFinal_ex using ctx2. +// This is necessary because Go hash.Hash mandates that Sum has no effect +// on the underlying stream. In particular it is OK to Sum, then Write more, +// then Sum again, and the second Sum acts as if the first didn't happen. +// It is written in C because Sum() tend to be in the hot path, +// and doing one cgo call instead of two is a significant performance win. +static inline int +go_hash_sum(const _EVP_MD_CTX_PTR ctx, _EVP_MD_CTX_PTR ctx2, unsigned char *out, mkcgo_err_state *_err_state) +{ + if (_mkcgo_EVP_MD_CTX_copy(ctx2, ctx, _err_state) != 1) + return -1; + if (_mkcgo_EVP_DigestFinal_ex(ctx2, out, NULL, _err_state) <= 0) + return -2; + return 1; +} +*/ +import "C" +import ( + "unsafe" +) + +func HashSum(ctx1, ctx2 EVP_MD_CTX_PTR, out []byte) error { + var errst C.mkcgo_err_state + if code := C.go_hash_sum(ctx1, ctx2, (*C.uchar)(unsafe.SliceData(out)), mkcgoNoEscape(&errst)); code != 1 { + msg := "go_hash_sum" + switch code { + case -1: + msg = "EVP_MD_CTX_copy" + case -2: + msg = "EVP_DigestFinal_ex" + } + return newMkcgoErr(msg, errst) + } + return nil +} diff --git a/internal/ossl/ossl_nocgo.go b/internal/ossl/ossl_nocgo.go new file mode 100644 index 00000000..bc0e7a00 --- /dev/null +++ b/internal/ossl/ossl_nocgo.go @@ -0,0 +1,34 @@ +//go:build !cgo + +package ossl + +import "unsafe" + +// HashSum copies ctx1 into ctx2 and calls EVP_DigestFinal_ex using ctx2. +// This is necessary because Go hash.Hash mandates that Sum has no effect +// on the underlying stream. In particular it is OK to Sum, then Write more, +// then Sum again, and the second Sum acts as if the first didn't happen. +func HashSum(ctx1, ctx2 EVP_MD_CTX_PTR, out []byte) error { + // Clear any existing errors + ERR_clear_error() + + // Copy ctx1 to ctx2 using EVP_MD_CTX_copy_ex + code, err := EVP_MD_CTX_copy_ex(ctx2, ctx1) + if err != nil { + return err + } + if code != 1 { + return newMkcgoErr("EVP_MD_CTX_copy_ex", nil) + } + + // Finalize the hash using ctx2 + code, err = EVP_DigestFinal_ex(ctx2, (*byte)(unsafe.SliceData(out)), nil) + if err != nil { + return err + } + if code <= 0 { + return newMkcgoErr("EVP_DigestFinal_ex", nil) + } + + return nil +} diff --git a/internal/ossl/syscall_nocgo_darwin.go b/internal/ossl/syscall_nocgo_darwin.go new file mode 100644 index 00000000..d6a7523b --- /dev/null +++ b/internal/ossl/syscall_nocgo_darwin.go @@ -0,0 +1,5 @@ +//go:build !cgo && darwin + +package ossl + +//go:cgo_import_dynamic _ _ "/usr/lib/libSystem.B.dylib" diff --git a/internal/ossl/syscall_nocgo_linux.go b/internal/ossl/syscall_nocgo_linux.go new file mode 100644 index 00000000..20cb4556 --- /dev/null +++ b/internal/ossl/syscall_nocgo_linux.go @@ -0,0 +1,5 @@ +//go:build !cgo && linux + +package ossl + +//go:cgo_import_dynamic _ _ "libdl.so.2" diff --git a/internal/ossl/syscall_nocgo_unix.go b/internal/ossl/syscall_nocgo_unix.go new file mode 100644 index 00000000..81d6d71c --- /dev/null +++ b/internal/ossl/syscall_nocgo_unix.go @@ -0,0 +1,55 @@ +//go:build !cgo && unix + +package ossl + +import ( + "syscall" + "unsafe" + + _ "github.com/golang-fips/openssl/v2/internal/fakecgo" +) + +//go:linkname runtime_cgocall runtime.cgocall + +//go:noescape +func runtime_cgocall(fn uintptr, arg unsafe.Pointer) int32 // from runtime/sys_libc.go + +//go:linkname noescape +//go:nosplit +func noescape(p unsafe.Pointer) unsafe.Pointer { + x := uintptr(p) + return unsafe.Pointer(x ^ 0) +} + +type libcCallInfo struct { + fn uintptr + n uintptr // number of parameters + args uintptr // parameters + r1, r2 uintptr // return values +} + +var syscallNABI0 uintptr + +//go:nosplit +func syscallN(fn uintptr, args ...uintptr) (r1, r2 uintptr, err syscall.Errno) { + libcArgs := libcCallInfo{ + fn: fn, + n: uintptr(len(args)), + } + if libcArgs.n != 0 { + libcArgs.args = uintptr(noescape(unsafe.Pointer(&args[0]))) + } + runtime_cgocall(syscallNABI0, unsafe.Pointer(&libcArgs)) + return libcArgs.r1, libcArgs.r2, 0 +} + +func dlsym(handle unsafe.Pointer, symbol string, optional bool) uintptr { + r0 := Dlsym(handle, unsafe.StringData(symbol)) + if r0 == nil { + if !optional { + panic("cannot get required symbol " + symbol) + } + return 0 + } + return uintptr(r0) +} diff --git a/internal/ossl/syscall_nocgo_windows.go b/internal/ossl/syscall_nocgo_windows.go new file mode 100644 index 00000000..73e75d91 --- /dev/null +++ b/internal/ossl/syscall_nocgo_windows.go @@ -0,0 +1,28 @@ +//go:build !cgo && windows + +package ossl + +import ( + "syscall" + "unsafe" +) + +var modkernel32 = syscall.NewLazyDLL("kernel32.dll") +var procGetProcAddress = modkernel32.NewProc("GetProcAddress") + +//go:nosplit +func syscallN(fn uintptr, args ...uintptr) (r1, r2 uintptr, err syscall.Errno) { + r1, r2, err = syscall.SyscallN(fn, args...) + return +} + +func dlsym(handle unsafe.Pointer, symbol string, optional bool) uintptr { + r0, _, err := syscall.SyscallN(procGetProcAddress.Addr(), uintptr(handle), uintptr(unsafe.Pointer(unsafe.StringData(symbol)))) + if err != 0 { + if !optional { + panic("cannot get required symbol " + symbol + ": " + err.Error()) + } + return 0 + } + return r0 +} diff --git a/internal/ossl/zdl.s b/internal/ossl/zdl.s new file mode 100644 index 00000000..58f4736b --- /dev/null +++ b/internal/ossl/zdl.s @@ -0,0 +1,51 @@ +// Code generated by mkcgo. DO NOT EDIT. + +//go:build !cgo && (unix) + +#include "textflag.h" + + +#ifndef GOARCH_amd64 +#ifndef GOARCH_arm64 +#ifndef GOARCH_riscv64 +#ifndef GOARCH_loong64 +#ifndef GOARCH_mips64 +#ifndef GOARCH_mips64le +#ifndef GOARCH_ppc64 +#ifndef GOARCH_ppc64le +#ifndef GOARCH_sparc64 +#define _GOPTRSIZE 4 +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif + + +#ifndef _GOPTRSIZE +#define _GOPTRSIZE 8 +#endif +TEXT _mkcgo_dlclose_trampoline<>(SB),NOSPLIT,$0-0 + JMP _mkcgo_dlclose(SB) +GLOBL ·_mkcgo_dlclose_trampoline_addr(SB), RODATA, $_GOPTRSIZE +DATA ·_mkcgo_dlclose_trampoline_addr(SB)/_GOPTRSIZE, $_mkcgo_dlclose_trampoline<>(SB) + +TEXT _mkcgo_dlerror_trampoline<>(SB),NOSPLIT,$0-0 + JMP _mkcgo_dlerror(SB) +GLOBL ·_mkcgo_dlerror_trampoline_addr(SB), RODATA, $_GOPTRSIZE +DATA ·_mkcgo_dlerror_trampoline_addr(SB)/_GOPTRSIZE, $_mkcgo_dlerror_trampoline<>(SB) + +TEXT _mkcgo_dlopen_trampoline<>(SB),NOSPLIT,$0-0 + JMP _mkcgo_dlopen(SB) +GLOBL ·_mkcgo_dlopen_trampoline_addr(SB), RODATA, $_GOPTRSIZE +DATA ·_mkcgo_dlopen_trampoline_addr(SB)/_GOPTRSIZE, $_mkcgo_dlopen_trampoline<>(SB) + +TEXT _mkcgo_dlsym_trampoline<>(SB),NOSPLIT,$0-0 + JMP _mkcgo_dlsym(SB) +GLOBL ·_mkcgo_dlsym_trampoline_addr(SB), RODATA, $_GOPTRSIZE +DATA ·_mkcgo_dlsym_trampoline_addr(SB)/_GOPTRSIZE, $_mkcgo_dlsym_trampoline<>(SB) + diff --git a/internal/ossl/zdl_nocgo.go b/internal/ossl/zdl_nocgo.go new file mode 100644 index 00000000..a6271a69 --- /dev/null +++ b/internal/ossl/zdl_nocgo.go @@ -0,0 +1,45 @@ +// Code generated by mkcgo. DO NOT EDIT. + +//go:build !cgo && unix + +package ossl + +import ( + "runtime" + "unsafe" +) + +//go:cgo_import_dynamic _mkcgo_dlclose dlclose "" +//go:cgo_import_dynamic _mkcgo_dlerror dlerror "" +//go:cgo_import_dynamic _mkcgo_dlopen dlopen "" +//go:cgo_import_dynamic _mkcgo_dlsym dlsym "" + +var _mkcgo_dlclose_trampoline_addr uintptr + +func Dlclose(handle unsafe.Pointer) int32 { + r0, _, _ := syscallN(_mkcgo_dlclose_trampoline_addr, uintptr(handle)) + return int32(r0) +} + +var _mkcgo_dlerror_trampoline_addr uintptr + +func Dlerror() *byte { + r0, _, _ := syscallN(_mkcgo_dlerror_trampoline_addr) + return (*byte)(unsafe.Pointer(r0)) +} + +var _mkcgo_dlopen_trampoline_addr uintptr + +func Dlopen(path *byte, flags int32) unsafe.Pointer { + r0, _, _ := syscallN(_mkcgo_dlopen_trampoline_addr, uintptr(unsafe.Pointer(path)), uintptr(flags)) + runtime.KeepAlive(path) + return unsafe.Pointer(r0) +} + +var _mkcgo_dlsym_trampoline_addr uintptr + +func Dlsym(handle unsafe.Pointer, symbol *byte) unsafe.Pointer { + r0, _, _ := syscallN(_mkcgo_dlsym_trampoline_addr, uintptr(handle), uintptr(unsafe.Pointer(symbol))) + runtime.KeepAlive(symbol) + return unsafe.Pointer(r0) +} diff --git a/internal/ossl/zossl.go b/internal/ossl/zossl.go index 9079f7a0..31c043ae 100644 --- a/internal/ossl/zossl.go +++ b/internal/ossl/zossl.go @@ -346,16 +346,16 @@ func ERR_clear_error() { C._mkcgo_ERR_clear_error() } -func ERR_error_string_n(e uint32, buf *byte, len int) { +func ERR_error_string_n(e uint64, buf *byte, len int) { C._mkcgo_ERR_error_string_n(C.ulong(e), (*C.char)(unsafe.Pointer(buf)), C.size_t(len)) } -func ERR_get_error_all(file **byte, line *int32, __func **byte, data **byte, flags *int32) uint32 { - return uint32(C._mkcgo_ERR_get_error_all((**C.char)(unsafe.Pointer(file)), (*C.int)(unsafe.Pointer(line)), (**C.char)(unsafe.Pointer(__func)), (**C.char)(unsafe.Pointer(data)), (*C.int)(unsafe.Pointer(flags)))) +func ERR_get_error_all(file **byte, line *int32, __func **byte, data **byte, flags *int32) uint64 { + return uint64(C._mkcgo_ERR_get_error_all((**C.char)(unsafe.Pointer(file)), (*C.int)(unsafe.Pointer(line)), (**C.char)(unsafe.Pointer(__func)), (**C.char)(unsafe.Pointer(data)), (*C.int)(unsafe.Pointer(flags)))) } -func ERR_get_error_line(file **byte, line *int32) uint32 { - return uint32(C._mkcgo_ERR_get_error_line((**C.char)(unsafe.Pointer(file)), (*C.int)(unsafe.Pointer(line)))) +func ERR_get_error_line(file **byte, line *int32) uint64 { + return uint64(C._mkcgo_ERR_get_error_line((**C.char)(unsafe.Pointer(file)), (*C.int)(unsafe.Pointer(line)))) } func EVP_CIPHER_CTX_ctrl(ctx EVP_CIPHER_CTX_PTR, __type int32, arg int32, ptr unsafe.Pointer) (int32, error) { @@ -1272,8 +1272,8 @@ func OpenSSL_version_num_Available() bool { return C._mkcgo_available_OpenSSL_version_num() != 0 } -func OpenSSL_version_num() uint32 { - return uint32(C._mkcgo_OpenSSL_version_num()) +func OpenSSL_version_num() uint64 { + return uint64(C._mkcgo_OpenSSL_version_num()) } func PKCS5_PBKDF2_HMAC(pass *byte, passlen int32, salt *byte, saltlen int32, iter int32, digest EVP_MD_PTR, keylen int32, out *byte) (int32, error) { diff --git a/internal/ossl/zossl_nocgo.go b/internal/ossl/zossl_nocgo.go new file mode 100644 index 00000000..611f2684 --- /dev/null +++ b/internal/ossl/zossl_nocgo.go @@ -0,0 +1,2906 @@ +// Code generated by mkcgo. DO NOT EDIT. + +//go:build !cgo + +package ossl + +import ( + "runtime" + "unsafe" +) + +type OPENSSL_INIT_SETTINGS_PTR unsafe.Pointer +type OSSL_LIB_CTX_PTR unsafe.Pointer +type OSSL_PROVIDER_PTR unsafe.Pointer +type ENGINE_PTR unsafe.Pointer +type EVP_PKEY_PTR unsafe.Pointer +type EVP_PKEY_CTX_PTR unsafe.Pointer +type EVP_MD_PTR unsafe.Pointer +type EVP_MD_CTX_PTR unsafe.Pointer +type HMAC_CTX_PTR unsafe.Pointer +type EVP_CIPHER_PTR unsafe.Pointer +type EVP_CIPHER_CTX_PTR unsafe.Pointer +type EC_KEY_PTR unsafe.Pointer +type EC_POINT_PTR unsafe.Pointer +type EC_GROUP_PTR unsafe.Pointer +type RSA_PTR unsafe.Pointer +type BIGNUM_PTR unsafe.Pointer +type BN_CTX_PTR unsafe.Pointer +type EVP_MAC_PTR unsafe.Pointer +type EVP_MAC_CTX_PTR unsafe.Pointer +type OSSL_PARAM_BLD_PTR unsafe.Pointer +type OSSL_PARAM_PTR unsafe.Pointer +type EVP_SIGNATURE_PTR unsafe.Pointer +type DSA_PTR unsafe.Pointer +type EVP_KDF_PTR unsafe.Pointer +type EVP_KDF_CTX_PTR unsafe.Pointer +type Point_conversion_form_t = int32 + +const ( + POINT_CONVERSION_UNCOMPRESSED = 4 + OPENSSL_INIT_LOAD_CRYPTO_STRINGS = 0x00000002 + OPENSSL_INIT_ADD_ALL_CIPHERS = 0x00000004 + OPENSSL_INIT_ADD_ALL_DIGESTS = 0x00000008 + OPENSSL_INIT_LOAD_CONFIG = 0x00000040 + EVP_CTRL_GCM_GET_TAG = 0x10 + EVP_CTRL_GCM_SET_TAG = 0x11 + EVP_PKEY_CTRL_MD = 1 + EVP_PKEY_RSA = 6 + EVP_PKEY_EC = 408 + EVP_PKEY_TLS1_PRF = 1021 + EVP_PKEY_HKDF = 1036 + EVP_PKEY_ED25519 = 1087 + EVP_PKEY_DSA = 116 + EVP_PKEY_OP_DERIVE = (1 << 10) + EVP_MAX_MD_SIZE = 64 + EVP_PKEY_PUBLIC_KEY = 0x86 + EVP_PKEY_KEYPAIR = 0x87 + EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID = 0x1001 + EVP_KDF_HKDF_MODE_EXTRACT_ONLY = 1 + EVP_KDF_HKDF_MODE_EXPAND_ONLY = 2 + EVP_PKEY_CTRL_TLS_MD = 0x1000 + EVP_PKEY_CTRL_TLS_SECRET = 0x1001 + EVP_PKEY_CTRL_TLS_SEED = 0x1002 + EVP_PKEY_CTRL_HKDF_MD = 0x1003 + EVP_PKEY_CTRL_HKDF_SALT = 0x1004 + EVP_PKEY_CTRL_HKDF_KEY = 0x1005 + EVP_PKEY_CTRL_HKDF_INFO = 0x1006 + EVP_PKEY_CTRL_HKDF_MODE = 0x1007 + NID_X9_62_prime256v1 = 415 + NID_secp224r1 = 713 + NID_secp384r1 = 715 + NID_secp521r1 = 716 + RSA_PKCS1_PADDING = 1 + RSA_NO_PADDING = 3 + RSA_PKCS1_OAEP_PADDING = 4 + RSA_PKCS1_PSS_PADDING = 6 + RSA_PSS_SALTLEN_DIGEST = -1 + RSA_PSS_SALTLEN_AUTO = -2 + RSA_PSS_SALTLEN_MAX_SIGN = -2 + RSA_PSS_SALTLEN_MAX = -3 + EVP_PKEY_CTRL_RSA_PADDING = 0x1001 + EVP_PKEY_CTRL_RSA_PSS_SALTLEN = 0x1002 + EVP_PKEY_CTRL_RSA_KEYGEN_BITS = 0x1003 + EVP_PKEY_CTRL_RSA_MGF1_MD = 0x1005 + EVP_PKEY_CTRL_RSA_OAEP_MD = 0x1009 + EVP_PKEY_CTRL_RSA_OAEP_LABEL = 0x100A + EVP_PKEY_CTRL_DSA_PARAMGEN_BITS = 0x1001 + EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS = 0x1002 + OSSL_PARAM_INTEGER = 1 + OSSL_PARAM_OCTET_STRING = 5 +) + +var _mkcgo_BN_bin2bn uintptr + +func BN_bin2bn(arg0 *byte, arg1 int32, arg2 BIGNUM_PTR) (BIGNUM_PTR, error) { + r0, _, _ := syscallN(_mkcgo_BN_bin2bn, uintptr(unsafe.Pointer(arg0)), uintptr(arg1), uintptr(arg2)) + runtime.KeepAlive(arg0) + runtime.KeepAlive(arg2) + if BIGNUM_PTR(r0) == nil { + return nil, newMkcgoErr("BN_bin2bn", nil) + } + return BIGNUM_PTR(r0), nil +} + +var _mkcgo_BN_bn2binpad uintptr + +func BN_bn2binpad(a BIGNUM_PTR, to *byte, tolen int32) (int32, error) { + r0, _, _ := syscallN(_mkcgo_BN_bn2binpad, uintptr(a), uintptr(unsafe.Pointer(to)), uintptr(tolen)) + runtime.KeepAlive(a) + runtime.KeepAlive(to) + if int32(r0) == -1 { + return 0, newMkcgoErr("BN_bn2binpad", nil) + } + return int32(r0), nil +} + +var _mkcgo_BN_bn2lebinpad uintptr + +func BN_bn2lebinpad(a BIGNUM_PTR, to *byte, tolen int32) (int32, error) { + r0, _, _ := syscallN(_mkcgo_BN_bn2lebinpad, uintptr(a), uintptr(unsafe.Pointer(to)), uintptr(tolen)) + runtime.KeepAlive(a) + runtime.KeepAlive(to) + if int32(r0) == -1 { + return 0, newMkcgoErr("BN_bn2lebinpad", nil) + } + return int32(r0), nil +} + +var _mkcgo_BN_clear uintptr + +func BN_clear(arg0 BIGNUM_PTR) { + syscallN(_mkcgo_BN_clear, uintptr(arg0)) + runtime.KeepAlive(arg0) +} + +var _mkcgo_BN_clear_free uintptr + +func BN_clear_free(arg0 BIGNUM_PTR) { + syscallN(_mkcgo_BN_clear_free, uintptr(arg0)) + runtime.KeepAlive(arg0) +} + +var _mkcgo_BN_free uintptr + +func BN_free(arg0 BIGNUM_PTR) { + syscallN(_mkcgo_BN_free, uintptr(arg0)) + runtime.KeepAlive(arg0) +} + +var _mkcgo_BN_lebin2bn uintptr + +func BN_lebin2bn(s *byte, len int32, ret BIGNUM_PTR) (BIGNUM_PTR, error) { + r0, _, _ := syscallN(_mkcgo_BN_lebin2bn, uintptr(unsafe.Pointer(s)), uintptr(len), uintptr(ret)) + runtime.KeepAlive(s) + runtime.KeepAlive(ret) + if BIGNUM_PTR(r0) == nil { + return nil, newMkcgoErr("BN_lebin2bn", nil) + } + return BIGNUM_PTR(r0), nil +} + +var _mkcgo_BN_new uintptr + +func BN_new() (BIGNUM_PTR, error) { + r0, _, _ := syscallN(_mkcgo_BN_new) + if BIGNUM_PTR(r0) == nil { + return nil, newMkcgoErr("BN_new", nil) + } + return BIGNUM_PTR(r0), nil +} + +var _mkcgo_BN_num_bits uintptr + +func BN_num_bits(arg0 BIGNUM_PTR) int32 { + r0, _, _ := syscallN(_mkcgo_BN_num_bits, uintptr(arg0)) + runtime.KeepAlive(arg0) + return int32(r0) +} + +var _mkcgo_CRYPTO_free uintptr + +func CRYPTO_free(str unsafe.Pointer, file *byte, line int32) { + syscallN(_mkcgo_CRYPTO_free, uintptr(str), uintptr(unsafe.Pointer(file)), uintptr(line)) + runtime.KeepAlive(file) +} + +var _mkcgo_CRYPTO_malloc uintptr + +func CRYPTO_malloc(num int, file *byte, line int32) (unsafe.Pointer, error) { + r0, _, _ := syscallN(_mkcgo_CRYPTO_malloc, uintptr(num), uintptr(unsafe.Pointer(file)), uintptr(line)) + runtime.KeepAlive(file) + if unsafe.Pointer(r0) == nil { + return nil, newMkcgoErr("CRYPTO_malloc", nil) + } + return unsafe.Pointer(r0), nil +} + +var _mkcgo_DSA_free uintptr + +func DSA_free(r DSA_PTR) { + syscallN(_mkcgo_DSA_free, uintptr(r)) + runtime.KeepAlive(r) +} + +var _mkcgo_DSA_generate_key uintptr + +func DSA_generate_key(a DSA_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_DSA_generate_key, uintptr(a)) + runtime.KeepAlive(a) + if int32(r0) <= 0 { + return 0, newMkcgoErr("DSA_generate_key", nil) + } + return int32(r0), nil +} + +var _mkcgo_DSA_get0_key uintptr + +func DSA_get0_key(d DSA_PTR, pub_key *BIGNUM_PTR, priv_key *BIGNUM_PTR) { + syscallN(_mkcgo_DSA_get0_key, uintptr(d), uintptr(unsafe.Pointer(pub_key)), uintptr(unsafe.Pointer(priv_key))) + runtime.KeepAlive(d) + runtime.KeepAlive(pub_key) + runtime.KeepAlive(priv_key) +} + +var _mkcgo_DSA_get0_pqg uintptr + +func DSA_get0_pqg(d DSA_PTR, p *BIGNUM_PTR, q *BIGNUM_PTR, g *BIGNUM_PTR) { + syscallN(_mkcgo_DSA_get0_pqg, uintptr(d), uintptr(unsafe.Pointer(p)), uintptr(unsafe.Pointer(q)), uintptr(unsafe.Pointer(g))) + runtime.KeepAlive(d) + runtime.KeepAlive(p) + runtime.KeepAlive(q) + runtime.KeepAlive(g) +} + +var _mkcgo_DSA_new uintptr + +func DSA_new() (DSA_PTR, error) { + r0, _, _ := syscallN(_mkcgo_DSA_new) + if DSA_PTR(r0) == nil { + return nil, newMkcgoErr("DSA_new", nil) + } + return DSA_PTR(r0), nil +} + +var _mkcgo_DSA_set0_key uintptr + +func DSA_set0_key(d DSA_PTR, pub_key BIGNUM_PTR, priv_key BIGNUM_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_DSA_set0_key, uintptr(d), uintptr(pub_key), uintptr(priv_key)) + runtime.KeepAlive(d) + runtime.KeepAlive(pub_key) + runtime.KeepAlive(priv_key) + if int32(r0) <= 0 { + return 0, newMkcgoErr("DSA_set0_key", nil) + } + return int32(r0), nil +} + +var _mkcgo_DSA_set0_pqg uintptr + +func DSA_set0_pqg(d DSA_PTR, p BIGNUM_PTR, q BIGNUM_PTR, g BIGNUM_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_DSA_set0_pqg, uintptr(d), uintptr(p), uintptr(q), uintptr(g)) + runtime.KeepAlive(d) + runtime.KeepAlive(p) + runtime.KeepAlive(q) + runtime.KeepAlive(g) + if int32(r0) <= 0 { + return 0, newMkcgoErr("DSA_set0_pqg", nil) + } + return int32(r0), nil +} + +var _mkcgo_EC_GROUP_free uintptr + +func EC_GROUP_free(group EC_GROUP_PTR) { + syscallN(_mkcgo_EC_GROUP_free, uintptr(group)) + runtime.KeepAlive(group) +} + +var _mkcgo_EC_GROUP_new_by_curve_name uintptr + +func EC_GROUP_new_by_curve_name(nid int32) (EC_GROUP_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EC_GROUP_new_by_curve_name, uintptr(nid)) + if EC_GROUP_PTR(r0) == nil { + return nil, newMkcgoErr("EC_GROUP_new_by_curve_name", nil) + } + return EC_GROUP_PTR(r0), nil +} + +var _mkcgo_EC_KEY_check_key uintptr + +func EC_KEY_check_key(key EC_KEY_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EC_KEY_check_key, uintptr(key)) + runtime.KeepAlive(key) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EC_KEY_check_key", nil) + } + return int32(r0), nil +} + +var _mkcgo_EC_KEY_free uintptr + +func EC_KEY_free(arg0 EC_KEY_PTR) { + syscallN(_mkcgo_EC_KEY_free, uintptr(arg0)) + runtime.KeepAlive(arg0) +} + +var _mkcgo_EC_KEY_get0_group uintptr + +func EC_KEY_get0_group(arg0 EC_KEY_PTR) EC_GROUP_PTR { + r0, _, _ := syscallN(_mkcgo_EC_KEY_get0_group, uintptr(arg0)) + runtime.KeepAlive(arg0) + return EC_GROUP_PTR(r0) +} + +var _mkcgo_EC_KEY_get0_private_key uintptr + +func EC_KEY_get0_private_key(arg0 EC_KEY_PTR) BIGNUM_PTR { + r0, _, _ := syscallN(_mkcgo_EC_KEY_get0_private_key, uintptr(arg0)) + runtime.KeepAlive(arg0) + return BIGNUM_PTR(r0) +} + +var _mkcgo_EC_KEY_get0_public_key uintptr + +func EC_KEY_get0_public_key(arg0 EC_KEY_PTR) EC_POINT_PTR { + r0, _, _ := syscallN(_mkcgo_EC_KEY_get0_public_key, uintptr(arg0)) + runtime.KeepAlive(arg0) + return EC_POINT_PTR(r0) +} + +var _mkcgo_EC_KEY_new_by_curve_name uintptr + +func EC_KEY_new_by_curve_name(arg0 int32) (EC_KEY_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EC_KEY_new_by_curve_name, uintptr(arg0)) + if EC_KEY_PTR(r0) == nil { + return nil, newMkcgoErr("EC_KEY_new_by_curve_name", nil) + } + return EC_KEY_PTR(r0), nil +} + +var _mkcgo_EC_KEY_set_private_key uintptr + +func EC_KEY_set_private_key(arg0 EC_KEY_PTR, arg1 BIGNUM_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EC_KEY_set_private_key, uintptr(arg0), uintptr(arg1)) + runtime.KeepAlive(arg0) + runtime.KeepAlive(arg1) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EC_KEY_set_private_key", nil) + } + return int32(r0), nil +} + +var _mkcgo_EC_KEY_set_public_key uintptr + +func EC_KEY_set_public_key(key EC_KEY_PTR, pub EC_POINT_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EC_KEY_set_public_key, uintptr(key), uintptr(pub)) + runtime.KeepAlive(key) + runtime.KeepAlive(pub) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EC_KEY_set_public_key", nil) + } + return int32(r0), nil +} + +var _mkcgo_EC_KEY_set_public_key_affine_coordinates uintptr + +func EC_KEY_set_public_key_affine_coordinates(key EC_KEY_PTR, x BIGNUM_PTR, y BIGNUM_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EC_KEY_set_public_key_affine_coordinates, uintptr(key), uintptr(x), uintptr(y)) + runtime.KeepAlive(key) + runtime.KeepAlive(x) + runtime.KeepAlive(y) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EC_KEY_set_public_key_affine_coordinates", nil) + } + return int32(r0), nil +} + +var _mkcgo_EC_POINT_free uintptr + +func EC_POINT_free(arg0 EC_POINT_PTR) { + syscallN(_mkcgo_EC_POINT_free, uintptr(arg0)) + runtime.KeepAlive(arg0) +} + +var _mkcgo_EC_POINT_get_affine_coordinates_GFp uintptr + +func EC_POINT_get_affine_coordinates_GFp(arg0 EC_GROUP_PTR, arg1 EC_POINT_PTR, arg2 BIGNUM_PTR, arg3 BIGNUM_PTR, arg4 BN_CTX_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EC_POINT_get_affine_coordinates_GFp, uintptr(arg0), uintptr(arg1), uintptr(arg2), uintptr(arg3), uintptr(arg4)) + runtime.KeepAlive(arg0) + runtime.KeepAlive(arg1) + runtime.KeepAlive(arg2) + runtime.KeepAlive(arg3) + runtime.KeepAlive(arg4) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EC_POINT_get_affine_coordinates_GFp", nil) + } + return int32(r0), nil +} + +var _mkcgo_EC_POINT_mul uintptr + +func EC_POINT_mul(group EC_GROUP_PTR, r EC_POINT_PTR, n BIGNUM_PTR, q EC_POINT_PTR, m BIGNUM_PTR, ctx BN_CTX_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EC_POINT_mul, uintptr(group), uintptr(r), uintptr(n), uintptr(q), uintptr(m), uintptr(ctx)) + runtime.KeepAlive(group) + runtime.KeepAlive(r) + runtime.KeepAlive(n) + runtime.KeepAlive(q) + runtime.KeepAlive(m) + runtime.KeepAlive(ctx) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EC_POINT_mul", nil) + } + return int32(r0), nil +} + +var _mkcgo_EC_POINT_new uintptr + +func EC_POINT_new(arg0 EC_GROUP_PTR) (EC_POINT_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EC_POINT_new, uintptr(arg0)) + runtime.KeepAlive(arg0) + if EC_POINT_PTR(r0) == nil { + return nil, newMkcgoErr("EC_POINT_new", nil) + } + return EC_POINT_PTR(r0), nil +} + +var _mkcgo_EC_POINT_oct2point uintptr + +func EC_POINT_oct2point(group EC_GROUP_PTR, p EC_POINT_PTR, buf *byte, len int, ctx BN_CTX_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EC_POINT_oct2point, uintptr(group), uintptr(p), uintptr(unsafe.Pointer(buf)), uintptr(len), uintptr(ctx)) + runtime.KeepAlive(group) + runtime.KeepAlive(p) + runtime.KeepAlive(buf) + runtime.KeepAlive(ctx) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EC_POINT_oct2point", nil) + } + return int32(r0), nil +} + +var _mkcgo_EC_POINT_point2oct uintptr + +func EC_POINT_point2oct(group EC_GROUP_PTR, p EC_POINT_PTR, form Point_conversion_form_t, buf *byte, len int, ctx BN_CTX_PTR) (int, error) { + r0, _, _ := syscallN(_mkcgo_EC_POINT_point2oct, uintptr(group), uintptr(p), uintptr(form), uintptr(unsafe.Pointer(buf)), uintptr(len), uintptr(ctx)) + runtime.KeepAlive(group) + runtime.KeepAlive(p) + runtime.KeepAlive(buf) + runtime.KeepAlive(ctx) + if int(r0) <= 0 { + return 0, newMkcgoErr("EC_POINT_point2oct", nil) + } + return int(r0), nil +} + +var _mkcgo_EC_POINT_set_affine_coordinates uintptr + +func EC_POINT_set_affine_coordinates(arg0 EC_GROUP_PTR, arg1 EC_POINT_PTR, arg2 BIGNUM_PTR, arg3 BIGNUM_PTR, arg4 BN_CTX_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EC_POINT_set_affine_coordinates, uintptr(arg0), uintptr(arg1), uintptr(arg2), uintptr(arg3), uintptr(arg4)) + runtime.KeepAlive(arg0) + runtime.KeepAlive(arg1) + runtime.KeepAlive(arg2) + runtime.KeepAlive(arg3) + runtime.KeepAlive(arg4) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EC_POINT_set_affine_coordinates", nil) + } + return int32(r0), nil +} + +var _mkcgo_ERR_clear_error uintptr + +func ERR_clear_error() { + syscallN(_mkcgo_ERR_clear_error) +} + +var _mkcgo_ERR_error_string_n uintptr + +func ERR_error_string_n(e uint64, buf *byte, len int) { + syscallN(_mkcgo_ERR_error_string_n, uintptr(e), uintptr(unsafe.Pointer(buf)), uintptr(len)) + runtime.KeepAlive(buf) +} + +var _mkcgo_ERR_get_error_all uintptr + +func ERR_get_error_all(file **byte, line *int32, __func **byte, data **byte, flags *int32) uint64 { + r0, _, _ := syscallN(_mkcgo_ERR_get_error_all, uintptr(unsafe.Pointer(file)), uintptr(unsafe.Pointer(line)), uintptr(unsafe.Pointer(__func)), uintptr(unsafe.Pointer(data)), uintptr(unsafe.Pointer(flags))) + runtime.KeepAlive(file) + runtime.KeepAlive(line) + runtime.KeepAlive(__func) + runtime.KeepAlive(data) + runtime.KeepAlive(flags) + return uint64(r0) +} + +var _mkcgo_ERR_get_error_line uintptr + +func ERR_get_error_line(file **byte, line *int32) uint64 { + r0, _, _ := syscallN(_mkcgo_ERR_get_error_line, uintptr(unsafe.Pointer(file)), uintptr(unsafe.Pointer(line))) + runtime.KeepAlive(file) + runtime.KeepAlive(line) + return uint64(r0) +} + +var _mkcgo_EVP_CIPHER_CTX_ctrl uintptr + +func EVP_CIPHER_CTX_ctrl(ctx EVP_CIPHER_CTX_PTR, __type int32, arg int32, ptr unsafe.Pointer) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_CIPHER_CTX_ctrl, uintptr(ctx), uintptr(__type), uintptr(arg), uintptr(ptr)) + runtime.KeepAlive(ctx) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_CIPHER_CTX_ctrl", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_CIPHER_CTX_free uintptr + +func EVP_CIPHER_CTX_free(arg0 EVP_CIPHER_CTX_PTR) { + syscallN(_mkcgo_EVP_CIPHER_CTX_free, uintptr(arg0)) + runtime.KeepAlive(arg0) +} + +var _mkcgo_EVP_CIPHER_CTX_new uintptr + +func EVP_CIPHER_CTX_new() (EVP_CIPHER_CTX_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EVP_CIPHER_CTX_new) + if EVP_CIPHER_CTX_PTR(r0) == nil { + return nil, newMkcgoErr("EVP_CIPHER_CTX_new", nil) + } + return EVP_CIPHER_CTX_PTR(r0), nil +} + +var _mkcgo_EVP_CIPHER_CTX_set_key_length uintptr + +func EVP_CIPHER_CTX_set_key_length(x EVP_CIPHER_CTX_PTR, keylen int32) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_CIPHER_CTX_set_key_length, uintptr(x), uintptr(keylen)) + runtime.KeepAlive(x) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_CIPHER_CTX_set_key_length", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_CIPHER_CTX_set_padding uintptr + +func EVP_CIPHER_CTX_set_padding(x EVP_CIPHER_CTX_PTR, padding int32) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_CIPHER_CTX_set_padding, uintptr(x), uintptr(padding)) + runtime.KeepAlive(x) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_CIPHER_CTX_set_padding", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_CIPHER_fetch uintptr + +func EVP_CIPHER_fetch(ctx OSSL_LIB_CTX_PTR, algorithm *byte, properties *byte) (EVP_CIPHER_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EVP_CIPHER_fetch, uintptr(ctx), uintptr(unsafe.Pointer(algorithm)), uintptr(unsafe.Pointer(properties))) + runtime.KeepAlive(ctx) + runtime.KeepAlive(algorithm) + runtime.KeepAlive(properties) + if EVP_CIPHER_PTR(r0) == nil { + return nil, newMkcgoErr("EVP_CIPHER_fetch", nil) + } + return EVP_CIPHER_PTR(r0), nil +} + +var _mkcgo_EVP_CIPHER_get0_name uintptr + +func EVP_CIPHER_get0_name(cipher EVP_CIPHER_PTR) *byte { + r0, _, _ := syscallN(_mkcgo_EVP_CIPHER_get0_name, uintptr(cipher)) + runtime.KeepAlive(cipher) + return (*byte)(unsafe.Pointer(r0)) +} + +var _mkcgo_EVP_CIPHER_get_block_size uintptr + +func EVP_CIPHER_get_block_size(cipher EVP_CIPHER_PTR) int32 { + r0, _, _ := syscallN(_mkcgo_EVP_CIPHER_get_block_size, uintptr(cipher)) + runtime.KeepAlive(cipher) + return int32(r0) +} + +var _mkcgo_EVP_CipherInit_ex uintptr + +func EVP_CipherInit_ex(ctx EVP_CIPHER_CTX_PTR, __type EVP_CIPHER_PTR, impl ENGINE_PTR, key *byte, iv *byte, enc int32) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_CipherInit_ex, uintptr(ctx), uintptr(__type), uintptr(impl), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(iv)), uintptr(enc)) + runtime.KeepAlive(ctx) + runtime.KeepAlive(__type) + runtime.KeepAlive(impl) + runtime.KeepAlive(key) + runtime.KeepAlive(iv) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_CipherInit_ex", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_CipherUpdate uintptr + +func EVP_CipherUpdate(ctx EVP_CIPHER_CTX_PTR, out *byte, outl *int32, in *byte, inl int32) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_CipherUpdate, uintptr(ctx), uintptr(unsafe.Pointer(out)), uintptr(unsafe.Pointer(outl)), uintptr(unsafe.Pointer(in)), uintptr(inl)) + runtime.KeepAlive(ctx) + runtime.KeepAlive(out) + runtime.KeepAlive(outl) + runtime.KeepAlive(in) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_CipherUpdate", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_DecryptFinal_ex uintptr + +func EVP_DecryptFinal_ex(ctx EVP_CIPHER_CTX_PTR, outm *byte, outl *int32) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_DecryptFinal_ex, uintptr(ctx), uintptr(unsafe.Pointer(outm)), uintptr(unsafe.Pointer(outl))) + runtime.KeepAlive(ctx) + runtime.KeepAlive(outm) + runtime.KeepAlive(outl) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_DecryptFinal_ex", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_DecryptInit_ex uintptr + +func EVP_DecryptInit_ex(ctx EVP_CIPHER_CTX_PTR, __type EVP_CIPHER_PTR, impl ENGINE_PTR, key *byte, iv *byte) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_DecryptInit_ex, uintptr(ctx), uintptr(__type), uintptr(impl), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(iv))) + runtime.KeepAlive(ctx) + runtime.KeepAlive(__type) + runtime.KeepAlive(impl) + runtime.KeepAlive(key) + runtime.KeepAlive(iv) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_DecryptInit_ex", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_DecryptUpdate uintptr + +func EVP_DecryptUpdate(ctx EVP_CIPHER_CTX_PTR, out *byte, outl *int32, in *byte, inl int32) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_DecryptUpdate, uintptr(ctx), uintptr(unsafe.Pointer(out)), uintptr(unsafe.Pointer(outl)), uintptr(unsafe.Pointer(in)), uintptr(inl)) + runtime.KeepAlive(ctx) + runtime.KeepAlive(out) + runtime.KeepAlive(outl) + runtime.KeepAlive(in) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_DecryptUpdate", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_Digest uintptr + +func EVP_Digest(data unsafe.Pointer, count int, md *byte, size *uint32, __type EVP_MD_PTR, impl ENGINE_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_Digest, uintptr(data), uintptr(count), uintptr(unsafe.Pointer(md)), uintptr(unsafe.Pointer(size)), uintptr(__type), uintptr(impl)) + runtime.KeepAlive(md) + runtime.KeepAlive(size) + runtime.KeepAlive(__type) + runtime.KeepAlive(impl) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_Digest", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_DigestFinal_ex uintptr + +func EVP_DigestFinal_ex(ctx EVP_MD_CTX_PTR, md *byte, s *uint32) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_DigestFinal_ex, uintptr(ctx), uintptr(unsafe.Pointer(md)), uintptr(unsafe.Pointer(s))) + runtime.KeepAlive(ctx) + runtime.KeepAlive(md) + runtime.KeepAlive(s) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_DigestFinal_ex", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_DigestInit uintptr + +func EVP_DigestInit(ctx EVP_MD_CTX_PTR, __type EVP_MD_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_DigestInit, uintptr(ctx), uintptr(__type)) + runtime.KeepAlive(ctx) + runtime.KeepAlive(__type) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_DigestInit", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_DigestInit_ex uintptr + +func EVP_DigestInit_ex(ctx EVP_MD_CTX_PTR, __type EVP_MD_PTR, impl ENGINE_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_DigestInit_ex, uintptr(ctx), uintptr(__type), uintptr(impl)) + runtime.KeepAlive(ctx) + runtime.KeepAlive(__type) + runtime.KeepAlive(impl) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_DigestInit_ex", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_DigestSign uintptr + +func EVP_DigestSign(ctx EVP_MD_CTX_PTR, sigret *byte, siglen *int, tbs *byte, tbslen int) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_DigestSign, uintptr(ctx), uintptr(unsafe.Pointer(sigret)), uintptr(unsafe.Pointer(siglen)), uintptr(unsafe.Pointer(tbs)), uintptr(tbslen)) + runtime.KeepAlive(ctx) + runtime.KeepAlive(sigret) + runtime.KeepAlive(siglen) + runtime.KeepAlive(tbs) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_DigestSign", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_DigestSignFinal uintptr + +func EVP_DigestSignFinal(ctx EVP_MD_CTX_PTR, sig *byte, siglen *int) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_DigestSignFinal, uintptr(ctx), uintptr(unsafe.Pointer(sig)), uintptr(unsafe.Pointer(siglen))) + runtime.KeepAlive(ctx) + runtime.KeepAlive(sig) + runtime.KeepAlive(siglen) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_DigestSignFinal", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_DigestSignInit uintptr + +func EVP_DigestSignInit(ctx EVP_MD_CTX_PTR, pctx *EVP_PKEY_CTX_PTR, __type EVP_MD_PTR, e ENGINE_PTR, pkey EVP_PKEY_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_DigestSignInit, uintptr(ctx), uintptr(unsafe.Pointer(pctx)), uintptr(__type), uintptr(e), uintptr(pkey)) + runtime.KeepAlive(ctx) + runtime.KeepAlive(pctx) + runtime.KeepAlive(__type) + runtime.KeepAlive(e) + runtime.KeepAlive(pkey) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_DigestSignInit", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_DigestUpdate uintptr + +func EVP_DigestUpdate(ctx EVP_MD_CTX_PTR, d unsafe.Pointer, cnt int) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_DigestUpdate, uintptr(ctx), uintptr(d), uintptr(cnt)) + runtime.KeepAlive(ctx) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_DigestUpdate", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_DigestVerify uintptr + +func EVP_DigestVerify(ctx EVP_MD_CTX_PTR, sigret *byte, siglen int, tbs *byte, tbslen int) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_DigestVerify, uintptr(ctx), uintptr(unsafe.Pointer(sigret)), uintptr(siglen), uintptr(unsafe.Pointer(tbs)), uintptr(tbslen)) + runtime.KeepAlive(ctx) + runtime.KeepAlive(sigret) + runtime.KeepAlive(tbs) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_DigestVerify", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_DigestVerifyFinal uintptr + +func EVP_DigestVerifyFinal(ctx EVP_MD_CTX_PTR, sig *byte, siglen int) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_DigestVerifyFinal, uintptr(ctx), uintptr(unsafe.Pointer(sig)), uintptr(siglen)) + runtime.KeepAlive(ctx) + runtime.KeepAlive(sig) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_DigestVerifyFinal", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_DigestVerifyInit uintptr + +func EVP_DigestVerifyInit(ctx EVP_MD_CTX_PTR, pctx *EVP_PKEY_CTX_PTR, __type EVP_MD_PTR, e ENGINE_PTR, pkey EVP_PKEY_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_DigestVerifyInit, uintptr(ctx), uintptr(unsafe.Pointer(pctx)), uintptr(__type), uintptr(e), uintptr(pkey)) + runtime.KeepAlive(ctx) + runtime.KeepAlive(pctx) + runtime.KeepAlive(__type) + runtime.KeepAlive(e) + runtime.KeepAlive(pkey) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_DigestVerifyInit", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_EncryptFinal_ex uintptr + +func EVP_EncryptFinal_ex(ctx EVP_CIPHER_CTX_PTR, out *byte, outl *int32) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_EncryptFinal_ex, uintptr(ctx), uintptr(unsafe.Pointer(out)), uintptr(unsafe.Pointer(outl))) + runtime.KeepAlive(ctx) + runtime.KeepAlive(out) + runtime.KeepAlive(outl) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_EncryptFinal_ex", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_EncryptInit_ex uintptr + +func EVP_EncryptInit_ex(ctx EVP_CIPHER_CTX_PTR, __type EVP_CIPHER_PTR, impl ENGINE_PTR, key *byte, iv *byte) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_EncryptInit_ex, uintptr(ctx), uintptr(__type), uintptr(impl), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(iv))) + runtime.KeepAlive(ctx) + runtime.KeepAlive(__type) + runtime.KeepAlive(impl) + runtime.KeepAlive(key) + runtime.KeepAlive(iv) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_EncryptInit_ex", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_EncryptUpdate uintptr + +func EVP_EncryptUpdate(ctx EVP_CIPHER_CTX_PTR, out *byte, outl *int32, in *byte, inl int32) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_EncryptUpdate, uintptr(ctx), uintptr(unsafe.Pointer(out)), uintptr(unsafe.Pointer(outl)), uintptr(unsafe.Pointer(in)), uintptr(inl)) + runtime.KeepAlive(ctx) + runtime.KeepAlive(out) + runtime.KeepAlive(outl) + runtime.KeepAlive(in) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_EncryptUpdate", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_KDF_CTX_free uintptr + +func EVP_KDF_CTX_free(ctx EVP_KDF_CTX_PTR) { + syscallN(_mkcgo_EVP_KDF_CTX_free, uintptr(ctx)) + runtime.KeepAlive(ctx) +} + +var _mkcgo_EVP_KDF_CTX_get_kdf_size uintptr + +func EVP_KDF_CTX_get_kdf_size(ctx EVP_KDF_CTX_PTR) (int, error) { + r0, _, _ := syscallN(_mkcgo_EVP_KDF_CTX_get_kdf_size, uintptr(ctx)) + runtime.KeepAlive(ctx) + if int(r0) <= 0 { + return 0, newMkcgoErr("EVP_KDF_CTX_get_kdf_size", nil) + } + return int(r0), nil +} + +var _mkcgo_EVP_KDF_CTX_new uintptr + +func EVP_KDF_CTX_new(kdf EVP_KDF_PTR) (EVP_KDF_CTX_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EVP_KDF_CTX_new, uintptr(kdf)) + runtime.KeepAlive(kdf) + if EVP_KDF_CTX_PTR(r0) == nil { + return nil, newMkcgoErr("EVP_KDF_CTX_new", nil) + } + return EVP_KDF_CTX_PTR(r0), nil +} + +var _mkcgo_EVP_KDF_CTX_set_params uintptr + +func EVP_KDF_CTX_set_params(ctx EVP_KDF_CTX_PTR, params OSSL_PARAM_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_KDF_CTX_set_params, uintptr(ctx), uintptr(params)) + runtime.KeepAlive(ctx) + runtime.KeepAlive(params) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_KDF_CTX_set_params", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_KDF_derive uintptr + +func EVP_KDF_derive(ctx EVP_KDF_CTX_PTR, key *byte, keylen int, params OSSL_PARAM_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_KDF_derive, uintptr(ctx), uintptr(unsafe.Pointer(key)), uintptr(keylen), uintptr(params)) + runtime.KeepAlive(ctx) + runtime.KeepAlive(key) + runtime.KeepAlive(params) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_KDF_derive", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_KDF_fetch uintptr + +func EVP_KDF_fetch(libctx OSSL_LIB_CTX_PTR, algorithm *byte, properties *byte) (EVP_KDF_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EVP_KDF_fetch, uintptr(libctx), uintptr(unsafe.Pointer(algorithm)), uintptr(unsafe.Pointer(properties))) + runtime.KeepAlive(libctx) + runtime.KeepAlive(algorithm) + runtime.KeepAlive(properties) + if EVP_KDF_PTR(r0) == nil { + return nil, newMkcgoErr("EVP_KDF_fetch", nil) + } + return EVP_KDF_PTR(r0), nil +} + +var _mkcgo_EVP_KDF_free uintptr + +func EVP_KDF_free(kdf EVP_KDF_PTR) { + syscallN(_mkcgo_EVP_KDF_free, uintptr(kdf)) + runtime.KeepAlive(kdf) +} + +var _mkcgo_EVP_MAC_CTX_dup uintptr + +func EVP_MAC_CTX_dup(arg0 EVP_MAC_CTX_PTR) (EVP_MAC_CTX_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EVP_MAC_CTX_dup, uintptr(arg0)) + runtime.KeepAlive(arg0) + if EVP_MAC_CTX_PTR(r0) == nil { + return nil, newMkcgoErr("EVP_MAC_CTX_dup", nil) + } + return EVP_MAC_CTX_PTR(r0), nil +} + +var _mkcgo_EVP_MAC_CTX_free uintptr + +func EVP_MAC_CTX_free(arg0 EVP_MAC_CTX_PTR) { + syscallN(_mkcgo_EVP_MAC_CTX_free, uintptr(arg0)) + runtime.KeepAlive(arg0) +} + +var _mkcgo_EVP_MAC_CTX_new uintptr + +func EVP_MAC_CTX_new(arg0 EVP_MAC_PTR) (EVP_MAC_CTX_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EVP_MAC_CTX_new, uintptr(arg0)) + runtime.KeepAlive(arg0) + if EVP_MAC_CTX_PTR(r0) == nil { + return nil, newMkcgoErr("EVP_MAC_CTX_new", nil) + } + return EVP_MAC_CTX_PTR(r0), nil +} + +var _mkcgo_EVP_MAC_CTX_set_params uintptr + +func EVP_MAC_CTX_set_params(ctx EVP_MAC_CTX_PTR, params OSSL_PARAM_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_MAC_CTX_set_params, uintptr(ctx), uintptr(params)) + runtime.KeepAlive(ctx) + runtime.KeepAlive(params) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_MAC_CTX_set_params", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_MAC_fetch uintptr + +func EVP_MAC_fetch(ctx OSSL_LIB_CTX_PTR, algorithm *byte, properties *byte) (EVP_MAC_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EVP_MAC_fetch, uintptr(ctx), uintptr(unsafe.Pointer(algorithm)), uintptr(unsafe.Pointer(properties))) + runtime.KeepAlive(ctx) + runtime.KeepAlive(algorithm) + runtime.KeepAlive(properties) + if EVP_MAC_PTR(r0) == nil { + return nil, newMkcgoErr("EVP_MAC_fetch", nil) + } + return EVP_MAC_PTR(r0), nil +} + +var _mkcgo_EVP_MAC_final uintptr + +func EVP_MAC_final(ctx EVP_MAC_CTX_PTR, out *byte, outl *int, outsize int) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_MAC_final, uintptr(ctx), uintptr(unsafe.Pointer(out)), uintptr(unsafe.Pointer(outl)), uintptr(outsize)) + runtime.KeepAlive(ctx) + runtime.KeepAlive(out) + runtime.KeepAlive(outl) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_MAC_final", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_MAC_init uintptr + +func EVP_MAC_init(ctx EVP_MAC_CTX_PTR, key *byte, keylen int, params OSSL_PARAM_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_MAC_init, uintptr(ctx), uintptr(unsafe.Pointer(key)), uintptr(keylen), uintptr(params)) + runtime.KeepAlive(ctx) + runtime.KeepAlive(key) + runtime.KeepAlive(params) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_MAC_init", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_MAC_update uintptr + +func EVP_MAC_update(ctx EVP_MAC_CTX_PTR, data *byte, datalen int) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_MAC_update, uintptr(ctx), uintptr(unsafe.Pointer(data)), uintptr(datalen)) + runtime.KeepAlive(ctx) + runtime.KeepAlive(data) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_MAC_update", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_MD_CTX_copy uintptr + +func EVP_MD_CTX_copy(out EVP_MD_CTX_PTR, in EVP_MD_CTX_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_MD_CTX_copy, uintptr(out), uintptr(in)) + runtime.KeepAlive(out) + runtime.KeepAlive(in) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_MD_CTX_copy", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_MD_CTX_copy_ex uintptr + +func EVP_MD_CTX_copy_ex(out EVP_MD_CTX_PTR, in EVP_MD_CTX_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_MD_CTX_copy_ex, uintptr(out), uintptr(in)) + runtime.KeepAlive(out) + runtime.KeepAlive(in) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_MD_CTX_copy_ex", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_MD_CTX_free uintptr + +func EVP_MD_CTX_free(ctx EVP_MD_CTX_PTR) { + syscallN(_mkcgo_EVP_MD_CTX_free, uintptr(ctx)) + runtime.KeepAlive(ctx) +} + +var _mkcgo_EVP_MD_CTX_get_params uintptr + +func EVP_MD_CTX_get_params(ctx EVP_MD_CTX_PTR, params OSSL_PARAM_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_MD_CTX_get_params, uintptr(ctx), uintptr(params)) + runtime.KeepAlive(ctx) + runtime.KeepAlive(params) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_MD_CTX_get_params", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_MD_CTX_gettable_params uintptr + +func EVP_MD_CTX_gettable_params(ctx EVP_MD_CTX_PTR) (OSSL_PARAM_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EVP_MD_CTX_gettable_params, uintptr(ctx)) + runtime.KeepAlive(ctx) + if OSSL_PARAM_PTR(r0) == nil { + return nil, newMkcgoErr("EVP_MD_CTX_gettable_params", nil) + } + return OSSL_PARAM_PTR(r0), nil +} + +var _mkcgo_EVP_MD_CTX_new uintptr + +func EVP_MD_CTX_new() (EVP_MD_CTX_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EVP_MD_CTX_new) + if EVP_MD_CTX_PTR(r0) == nil { + return nil, newMkcgoErr("EVP_MD_CTX_new", nil) + } + return EVP_MD_CTX_PTR(r0), nil +} + +var _mkcgo_EVP_MD_CTX_set_params uintptr + +func EVP_MD_CTX_set_params(ctx EVP_MD_CTX_PTR, params OSSL_PARAM_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_MD_CTX_set_params, uintptr(ctx), uintptr(params)) + runtime.KeepAlive(ctx) + runtime.KeepAlive(params) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_MD_CTX_set_params", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_MD_CTX_settable_params uintptr + +func EVP_MD_CTX_settable_params(ctx EVP_MD_CTX_PTR) (OSSL_PARAM_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EVP_MD_CTX_settable_params, uintptr(ctx)) + runtime.KeepAlive(ctx) + if OSSL_PARAM_PTR(r0) == nil { + return nil, newMkcgoErr("EVP_MD_CTX_settable_params", nil) + } + return OSSL_PARAM_PTR(r0), nil +} + +var _mkcgo_EVP_MD_fetch uintptr + +func EVP_MD_fetch(ctx OSSL_LIB_CTX_PTR, algorithm *byte, properties *byte) (EVP_MD_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EVP_MD_fetch, uintptr(ctx), uintptr(unsafe.Pointer(algorithm)), uintptr(unsafe.Pointer(properties))) + runtime.KeepAlive(ctx) + runtime.KeepAlive(algorithm) + runtime.KeepAlive(properties) + if EVP_MD_PTR(r0) == nil { + return nil, newMkcgoErr("EVP_MD_fetch", nil) + } + return EVP_MD_PTR(r0), nil +} + +var _mkcgo_EVP_MD_free uintptr + +func EVP_MD_free(md EVP_MD_PTR) { + syscallN(_mkcgo_EVP_MD_free, uintptr(md)) + runtime.KeepAlive(md) +} + +var _mkcgo_EVP_MD_get0_name uintptr + +func EVP_MD_get0_name(md EVP_MD_PTR) *byte { + r0, _, _ := syscallN(_mkcgo_EVP_MD_get0_name, uintptr(md)) + runtime.KeepAlive(md) + return (*byte)(unsafe.Pointer(r0)) +} + +var _mkcgo_EVP_MD_get0_provider uintptr + +func EVP_MD_get0_provider(md EVP_MD_PTR) OSSL_PROVIDER_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_MD_get0_provider, uintptr(md)) + runtime.KeepAlive(md) + return OSSL_PROVIDER_PTR(r0) +} + +var _mkcgo_EVP_MD_get_block_size uintptr + +func EVP_MD_get_block_size(md EVP_MD_PTR) int32 { + r0, _, _ := syscallN(_mkcgo_EVP_MD_get_block_size, uintptr(md)) + runtime.KeepAlive(md) + return int32(r0) +} + +var _mkcgo_EVP_MD_get_size uintptr + +func EVP_MD_get_size(md EVP_MD_PTR) int32 { + r0, _, _ := syscallN(_mkcgo_EVP_MD_get_size, uintptr(md)) + runtime.KeepAlive(md) + return int32(r0) +} + +var _mkcgo_EVP_MD_get_type uintptr + +func EVP_MD_get_type(md EVP_MD_PTR) int32 { + r0, _, _ := syscallN(_mkcgo_EVP_MD_get_type, uintptr(md)) + runtime.KeepAlive(md) + return int32(r0) +} + +var _mkcgo_EVP_PKEY_CTX_add1_hkdf_info uintptr + +func EVP_PKEY_CTX_add1_hkdf_info(arg0 EVP_PKEY_CTX_PTR, arg1 *byte, arg2 int32) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_CTX_add1_hkdf_info, uintptr(arg0), uintptr(unsafe.Pointer(arg1)), uintptr(arg2)) + runtime.KeepAlive(arg0) + runtime.KeepAlive(arg1) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_CTX_add1_hkdf_info", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_CTX_ctrl uintptr + +func EVP_PKEY_CTX_ctrl(ctx EVP_PKEY_CTX_PTR, keytype int32, optype int32, cmd int32, p1 int32, p2 unsafe.Pointer) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_CTX_ctrl, uintptr(ctx), uintptr(keytype), uintptr(optype), uintptr(cmd), uintptr(p1), uintptr(p2)) + runtime.KeepAlive(ctx) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_CTX_ctrl", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_CTX_free uintptr + +func EVP_PKEY_CTX_free(arg0 EVP_PKEY_CTX_PTR) { + syscallN(_mkcgo_EVP_PKEY_CTX_free, uintptr(arg0)) + runtime.KeepAlive(arg0) +} + +var _mkcgo_EVP_PKEY_CTX_new uintptr + +func EVP_PKEY_CTX_new(arg0 EVP_PKEY_PTR, arg1 ENGINE_PTR) (EVP_PKEY_CTX_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_CTX_new, uintptr(arg0), uintptr(arg1)) + runtime.KeepAlive(arg0) + runtime.KeepAlive(arg1) + if EVP_PKEY_CTX_PTR(r0) == nil { + return nil, newMkcgoErr("EVP_PKEY_CTX_new", nil) + } + return EVP_PKEY_CTX_PTR(r0), nil +} + +var _mkcgo_EVP_PKEY_CTX_new_from_pkey uintptr + +func EVP_PKEY_CTX_new_from_pkey(libctx OSSL_LIB_CTX_PTR, pkey EVP_PKEY_PTR, propquery *byte) (EVP_PKEY_CTX_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_CTX_new_from_pkey, uintptr(libctx), uintptr(pkey), uintptr(unsafe.Pointer(propquery))) + runtime.KeepAlive(libctx) + runtime.KeepAlive(pkey) + runtime.KeepAlive(propquery) + if EVP_PKEY_CTX_PTR(r0) == nil { + return nil, newMkcgoErr("EVP_PKEY_CTX_new_from_pkey", nil) + } + return EVP_PKEY_CTX_PTR(r0), nil +} + +var _mkcgo_EVP_PKEY_CTX_new_id uintptr + +func EVP_PKEY_CTX_new_id(id int32, e ENGINE_PTR) (EVP_PKEY_CTX_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_CTX_new_id, uintptr(id), uintptr(e)) + runtime.KeepAlive(e) + if EVP_PKEY_CTX_PTR(r0) == nil { + return nil, newMkcgoErr("EVP_PKEY_CTX_new_id", nil) + } + return EVP_PKEY_CTX_PTR(r0), nil +} + +var _mkcgo_EVP_PKEY_CTX_set0_rsa_oaep_label uintptr + +func EVP_PKEY_CTX_set0_rsa_oaep_label(ctx EVP_PKEY_CTX_PTR, label unsafe.Pointer, len int32) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_CTX_set0_rsa_oaep_label, uintptr(ctx), uintptr(label), uintptr(len)) + runtime.KeepAlive(ctx) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_CTX_set0_rsa_oaep_label", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_CTX_set1_hkdf_key uintptr + +func EVP_PKEY_CTX_set1_hkdf_key(arg0 EVP_PKEY_CTX_PTR, arg1 *byte, arg2 int32) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_CTX_set1_hkdf_key, uintptr(arg0), uintptr(unsafe.Pointer(arg1)), uintptr(arg2)) + runtime.KeepAlive(arg0) + runtime.KeepAlive(arg1) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_CTX_set1_hkdf_key", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_CTX_set1_hkdf_salt uintptr + +func EVP_PKEY_CTX_set1_hkdf_salt(arg0 EVP_PKEY_CTX_PTR, arg1 *byte, arg2 int32) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_CTX_set1_hkdf_salt, uintptr(arg0), uintptr(unsafe.Pointer(arg1)), uintptr(arg2)) + runtime.KeepAlive(arg0) + runtime.KeepAlive(arg1) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_CTX_set1_hkdf_salt", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_CTX_set_hkdf_md uintptr + +func EVP_PKEY_CTX_set_hkdf_md(arg0 EVP_PKEY_CTX_PTR, arg1 EVP_MD_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_CTX_set_hkdf_md, uintptr(arg0), uintptr(arg1)) + runtime.KeepAlive(arg0) + runtime.KeepAlive(arg1) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_CTX_set_hkdf_md", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_CTX_set_hkdf_mode uintptr + +func EVP_PKEY_CTX_set_hkdf_mode(arg0 EVP_PKEY_CTX_PTR, arg1 int32) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_CTX_set_hkdf_mode, uintptr(arg0), uintptr(arg1)) + runtime.KeepAlive(arg0) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_CTX_set_hkdf_mode", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_Q_keygen uintptr + +func EVP_PKEY_Q_keygen_EC(ctx OSSL_LIB_CTX_PTR, propq *byte, __type *byte, arg1 *byte) (EVP_PKEY_PTR, error) { + var r0 uintptr + if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" { + r0, _, _ = syscallN(_mkcgo_EVP_PKEY_Q_keygen, uintptr(ctx), uintptr(unsafe.Pointer(propq)), uintptr(unsafe.Pointer(__type)), 0, 0, 0, 0, 0, uintptr(unsafe.Pointer(arg1))) + } else { + r0, _, _ = syscallN(_mkcgo_EVP_PKEY_Q_keygen, uintptr(ctx), uintptr(unsafe.Pointer(propq)), uintptr(unsafe.Pointer(__type)), uintptr(unsafe.Pointer(arg1))) + } + runtime.KeepAlive(ctx) + runtime.KeepAlive(propq) + runtime.KeepAlive(__type) + runtime.KeepAlive(arg1) + if EVP_PKEY_PTR(r0) == nil { + return nil, newMkcgoErr("EVP_PKEY_Q_keygen_EC", nil) + } + return EVP_PKEY_PTR(r0), nil +} + +func EVP_PKEY_Q_keygen_ED25519(ctx OSSL_LIB_CTX_PTR, propq *byte, __type *byte) (EVP_PKEY_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_Q_keygen, uintptr(ctx), uintptr(unsafe.Pointer(propq)), uintptr(unsafe.Pointer(__type))) + runtime.KeepAlive(ctx) + runtime.KeepAlive(propq) + runtime.KeepAlive(__type) + if EVP_PKEY_PTR(r0) == nil { + return nil, newMkcgoErr("EVP_PKEY_Q_keygen_ED25519", nil) + } + return EVP_PKEY_PTR(r0), nil +} + +func EVP_PKEY_Q_keygen_RSA(ctx OSSL_LIB_CTX_PTR, propq *byte, __type *byte, arg1 int) (EVP_PKEY_PTR, error) { + var r0 uintptr + if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" { + r0, _, _ = syscallN(_mkcgo_EVP_PKEY_Q_keygen, uintptr(ctx), uintptr(unsafe.Pointer(propq)), uintptr(unsafe.Pointer(__type)), 0, 0, 0, 0, 0, uintptr(arg1)) + } else { + r0, _, _ = syscallN(_mkcgo_EVP_PKEY_Q_keygen, uintptr(ctx), uintptr(unsafe.Pointer(propq)), uintptr(unsafe.Pointer(__type)), uintptr(arg1)) + } + runtime.KeepAlive(ctx) + runtime.KeepAlive(propq) + runtime.KeepAlive(__type) + if EVP_PKEY_PTR(r0) == nil { + return nil, newMkcgoErr("EVP_PKEY_Q_keygen_RSA", nil) + } + return EVP_PKEY_PTR(r0), nil +} + +var _mkcgo_EVP_PKEY_assign uintptr + +func EVP_PKEY_assign(pkey EVP_PKEY_PTR, __type int32, key unsafe.Pointer) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_assign, uintptr(pkey), uintptr(__type), uintptr(key)) + runtime.KeepAlive(pkey) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_assign", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_decrypt uintptr + +func EVP_PKEY_decrypt(arg0 EVP_PKEY_CTX_PTR, arg1 *byte, arg2 *int, arg3 *byte, arg4 int) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_decrypt, uintptr(arg0), uintptr(unsafe.Pointer(arg1)), uintptr(unsafe.Pointer(arg2)), uintptr(unsafe.Pointer(arg3)), uintptr(arg4)) + runtime.KeepAlive(arg0) + runtime.KeepAlive(arg1) + runtime.KeepAlive(arg2) + runtime.KeepAlive(arg3) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_decrypt", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_decrypt_init uintptr + +func EVP_PKEY_decrypt_init(arg0 EVP_PKEY_CTX_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_decrypt_init, uintptr(arg0)) + runtime.KeepAlive(arg0) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_decrypt_init", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_derive uintptr + +func EVP_PKEY_derive(ctx EVP_PKEY_CTX_PTR, key *byte, keylen *int) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_derive, uintptr(ctx), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(keylen))) + runtime.KeepAlive(ctx) + runtime.KeepAlive(key) + runtime.KeepAlive(keylen) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_derive", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_derive_init uintptr + +func EVP_PKEY_derive_init(ctx EVP_PKEY_CTX_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_derive_init, uintptr(ctx)) + runtime.KeepAlive(ctx) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_derive_init", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_derive_set_peer uintptr + +func EVP_PKEY_derive_set_peer(ctx EVP_PKEY_CTX_PTR, peer EVP_PKEY_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_derive_set_peer, uintptr(ctx), uintptr(peer)) + runtime.KeepAlive(ctx) + runtime.KeepAlive(peer) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_derive_set_peer", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_encrypt uintptr + +func EVP_PKEY_encrypt(arg0 EVP_PKEY_CTX_PTR, arg1 *byte, arg2 *int, arg3 *byte, arg4 int) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_encrypt, uintptr(arg0), uintptr(unsafe.Pointer(arg1)), uintptr(unsafe.Pointer(arg2)), uintptr(unsafe.Pointer(arg3)), uintptr(arg4)) + runtime.KeepAlive(arg0) + runtime.KeepAlive(arg1) + runtime.KeepAlive(arg2) + runtime.KeepAlive(arg3) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_encrypt", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_encrypt_init uintptr + +func EVP_PKEY_encrypt_init(arg0 EVP_PKEY_CTX_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_encrypt_init, uintptr(arg0)) + runtime.KeepAlive(arg0) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_encrypt_init", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_free uintptr + +func EVP_PKEY_free(arg0 EVP_PKEY_PTR) { + syscallN(_mkcgo_EVP_PKEY_free, uintptr(arg0)) + runtime.KeepAlive(arg0) +} + +var _mkcgo_EVP_PKEY_fromdata uintptr + +func EVP_PKEY_fromdata(ctx EVP_PKEY_CTX_PTR, pkey *EVP_PKEY_PTR, selection int32, params OSSL_PARAM_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_fromdata, uintptr(ctx), uintptr(unsafe.Pointer(pkey)), uintptr(selection), uintptr(params)) + runtime.KeepAlive(ctx) + runtime.KeepAlive(pkey) + runtime.KeepAlive(params) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_fromdata", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_fromdata_init uintptr + +func EVP_PKEY_fromdata_init(ctx EVP_PKEY_CTX_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_fromdata_init, uintptr(ctx)) + runtime.KeepAlive(ctx) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_fromdata_init", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_get0_DSA uintptr + +func EVP_PKEY_get0_DSA(pkey EVP_PKEY_PTR) (DSA_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_get0_DSA, uintptr(pkey)) + runtime.KeepAlive(pkey) + if DSA_PTR(r0) == nil { + return nil, newMkcgoErr("EVP_PKEY_get0_DSA", nil) + } + return DSA_PTR(r0), nil +} + +var _mkcgo_EVP_PKEY_get0_EC_KEY uintptr + +func EVP_PKEY_get0_EC_KEY(pkey EVP_PKEY_PTR) (EC_KEY_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_get0_EC_KEY, uintptr(pkey)) + runtime.KeepAlive(pkey) + if EC_KEY_PTR(r0) == nil { + return nil, newMkcgoErr("EVP_PKEY_get0_EC_KEY", nil) + } + return EC_KEY_PTR(r0), nil +} + +var _mkcgo_EVP_PKEY_get1_RSA uintptr + +func EVP_PKEY_get1_RSA(pkey EVP_PKEY_PTR) (RSA_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_get1_RSA, uintptr(pkey)) + runtime.KeepAlive(pkey) + if RSA_PTR(r0) == nil { + return nil, newMkcgoErr("EVP_PKEY_get1_RSA", nil) + } + return RSA_PTR(r0), nil +} + +var _mkcgo_EVP_PKEY_get1_encoded_public_key uintptr + +func EVP_PKEY_get1_encoded_public_key(pkey EVP_PKEY_PTR, ppub **byte) (int, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_get1_encoded_public_key, uintptr(pkey), uintptr(unsafe.Pointer(ppub))) + runtime.KeepAlive(pkey) + runtime.KeepAlive(ppub) + if int(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_get1_encoded_public_key", nil) + } + return int(r0), nil +} + +var _mkcgo_EVP_PKEY_get_bits uintptr + +func EVP_PKEY_get_bits(pkey EVP_PKEY_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_get_bits, uintptr(pkey)) + runtime.KeepAlive(pkey) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_get_bits", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_get_bn_param uintptr + +func EVP_PKEY_get_bn_param(pkey EVP_PKEY_PTR, key_name *byte, bn *BIGNUM_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_get_bn_param, uintptr(pkey), uintptr(unsafe.Pointer(key_name)), uintptr(unsafe.Pointer(bn))) + runtime.KeepAlive(pkey) + runtime.KeepAlive(key_name) + runtime.KeepAlive(bn) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_get_bn_param", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_get_raw_private_key uintptr + +func EVP_PKEY_get_raw_private_key(pkey EVP_PKEY_PTR, priv *byte, len *int) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_get_raw_private_key, uintptr(pkey), uintptr(unsafe.Pointer(priv)), uintptr(unsafe.Pointer(len))) + runtime.KeepAlive(pkey) + runtime.KeepAlive(priv) + runtime.KeepAlive(len) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_get_raw_private_key", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_get_raw_public_key uintptr + +func EVP_PKEY_get_raw_public_key(pkey EVP_PKEY_PTR, pub *byte, len *int) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_get_raw_public_key, uintptr(pkey), uintptr(unsafe.Pointer(pub)), uintptr(unsafe.Pointer(len))) + runtime.KeepAlive(pkey) + runtime.KeepAlive(pub) + runtime.KeepAlive(len) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_get_raw_public_key", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_get_size uintptr + +func EVP_PKEY_get_size(pkey EVP_PKEY_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_get_size, uintptr(pkey)) + runtime.KeepAlive(pkey) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_get_size", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_keygen uintptr + +func EVP_PKEY_keygen(ctx EVP_PKEY_CTX_PTR, ppkey *EVP_PKEY_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_keygen, uintptr(ctx), uintptr(unsafe.Pointer(ppkey))) + runtime.KeepAlive(ctx) + runtime.KeepAlive(ppkey) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_keygen", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_keygen_init uintptr + +func EVP_PKEY_keygen_init(ctx EVP_PKEY_CTX_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_keygen_init, uintptr(ctx)) + runtime.KeepAlive(ctx) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_keygen_init", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_new uintptr + +func EVP_PKEY_new() (EVP_PKEY_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_new) + if EVP_PKEY_PTR(r0) == nil { + return nil, newMkcgoErr("EVP_PKEY_new", nil) + } + return EVP_PKEY_PTR(r0), nil +} + +var _mkcgo_EVP_PKEY_new_raw_private_key uintptr + +func EVP_PKEY_new_raw_private_key(__type int32, e ENGINE_PTR, key *byte, keylen int) (EVP_PKEY_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_new_raw_private_key, uintptr(__type), uintptr(e), uintptr(unsafe.Pointer(key)), uintptr(keylen)) + runtime.KeepAlive(e) + runtime.KeepAlive(key) + if EVP_PKEY_PTR(r0) == nil { + return nil, newMkcgoErr("EVP_PKEY_new_raw_private_key", nil) + } + return EVP_PKEY_PTR(r0), nil +} + +var _mkcgo_EVP_PKEY_new_raw_public_key uintptr + +func EVP_PKEY_new_raw_public_key(__type int32, e ENGINE_PTR, key *byte, keylen int) (EVP_PKEY_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_new_raw_public_key, uintptr(__type), uintptr(e), uintptr(unsafe.Pointer(key)), uintptr(keylen)) + runtime.KeepAlive(e) + runtime.KeepAlive(key) + if EVP_PKEY_PTR(r0) == nil { + return nil, newMkcgoErr("EVP_PKEY_new_raw_public_key", nil) + } + return EVP_PKEY_PTR(r0), nil +} + +var _mkcgo_EVP_PKEY_paramgen uintptr + +func EVP_PKEY_paramgen(ctx EVP_PKEY_CTX_PTR, ppkey *EVP_PKEY_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_paramgen, uintptr(ctx), uintptr(unsafe.Pointer(ppkey))) + runtime.KeepAlive(ctx) + runtime.KeepAlive(ppkey) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_paramgen", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_paramgen_init uintptr + +func EVP_PKEY_paramgen_init(ctx EVP_PKEY_CTX_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_paramgen_init, uintptr(ctx)) + runtime.KeepAlive(ctx) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_paramgen_init", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_private_check uintptr + +func EVP_PKEY_private_check(ctx EVP_PKEY_CTX_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_private_check, uintptr(ctx)) + runtime.KeepAlive(ctx) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_private_check", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_public_check_quick uintptr + +func EVP_PKEY_public_check_quick(ctx EVP_PKEY_CTX_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_public_check_quick, uintptr(ctx)) + runtime.KeepAlive(ctx) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_public_check_quick", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_set1_EC_KEY uintptr + +func EVP_PKEY_set1_EC_KEY(pkey EVP_PKEY_PTR, key EC_KEY_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_set1_EC_KEY, uintptr(pkey), uintptr(key)) + runtime.KeepAlive(pkey) + runtime.KeepAlive(key) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_set1_EC_KEY", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_set1_encoded_public_key uintptr + +func EVP_PKEY_set1_encoded_public_key(pkey EVP_PKEY_PTR, pub *byte, publen int) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_set1_encoded_public_key, uintptr(pkey), uintptr(unsafe.Pointer(pub)), uintptr(publen)) + runtime.KeepAlive(pkey) + runtime.KeepAlive(pub) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_set1_encoded_public_key", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_sign uintptr + +func EVP_PKEY_sign(arg0 EVP_PKEY_CTX_PTR, arg1 *byte, arg2 *int, arg3 *byte, arg4 int) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_sign, uintptr(arg0), uintptr(unsafe.Pointer(arg1)), uintptr(unsafe.Pointer(arg2)), uintptr(unsafe.Pointer(arg3)), uintptr(arg4)) + runtime.KeepAlive(arg0) + runtime.KeepAlive(arg1) + runtime.KeepAlive(arg2) + runtime.KeepAlive(arg3) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_sign", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_sign_init uintptr + +func EVP_PKEY_sign_init(arg0 EVP_PKEY_CTX_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_sign_init, uintptr(arg0)) + runtime.KeepAlive(arg0) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_sign_init", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_up_ref uintptr + +func EVP_PKEY_up_ref(key EVP_PKEY_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_up_ref, uintptr(key)) + runtime.KeepAlive(key) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_up_ref", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_verify uintptr + +func EVP_PKEY_verify(ctx EVP_PKEY_CTX_PTR, sig *byte, siglen int, tbs *byte, tbslen int) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_verify, uintptr(ctx), uintptr(unsafe.Pointer(sig)), uintptr(siglen), uintptr(unsafe.Pointer(tbs)), uintptr(tbslen)) + runtime.KeepAlive(ctx) + runtime.KeepAlive(sig) + runtime.KeepAlive(tbs) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_verify", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_PKEY_verify_init uintptr + +func EVP_PKEY_verify_init(arg0 EVP_PKEY_CTX_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_PKEY_verify_init, uintptr(arg0)) + runtime.KeepAlive(arg0) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_PKEY_verify_init", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_SIGNATURE_fetch uintptr + +func EVP_SIGNATURE_fetch(ctx OSSL_LIB_CTX_PTR, algorithm *byte, properties *byte) (EVP_SIGNATURE_PTR, error) { + r0, _, _ := syscallN(_mkcgo_EVP_SIGNATURE_fetch, uintptr(ctx), uintptr(unsafe.Pointer(algorithm)), uintptr(unsafe.Pointer(properties))) + runtime.KeepAlive(ctx) + runtime.KeepAlive(algorithm) + runtime.KeepAlive(properties) + if EVP_SIGNATURE_PTR(r0) == nil { + return nil, newMkcgoErr("EVP_SIGNATURE_fetch", nil) + } + return EVP_SIGNATURE_PTR(r0), nil +} + +var _mkcgo_EVP_SIGNATURE_free uintptr + +func EVP_SIGNATURE_free(signature EVP_SIGNATURE_PTR) { + syscallN(_mkcgo_EVP_SIGNATURE_free, uintptr(signature)) + runtime.KeepAlive(signature) +} + +var _mkcgo_EVP_aes_128_cbc uintptr + +func EVP_aes_128_cbc() EVP_CIPHER_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_aes_128_cbc) + return EVP_CIPHER_PTR(r0) +} + +var _mkcgo_EVP_aes_128_ctr uintptr + +func EVP_aes_128_ctr() EVP_CIPHER_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_aes_128_ctr) + return EVP_CIPHER_PTR(r0) +} + +var _mkcgo_EVP_aes_128_ecb uintptr + +func EVP_aes_128_ecb() EVP_CIPHER_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_aes_128_ecb) + return EVP_CIPHER_PTR(r0) +} + +var _mkcgo_EVP_aes_128_gcm uintptr + +func EVP_aes_128_gcm() EVP_CIPHER_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_aes_128_gcm) + return EVP_CIPHER_PTR(r0) +} + +var _mkcgo_EVP_aes_192_cbc uintptr + +func EVP_aes_192_cbc() EVP_CIPHER_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_aes_192_cbc) + return EVP_CIPHER_PTR(r0) +} + +var _mkcgo_EVP_aes_192_ctr uintptr + +func EVP_aes_192_ctr() EVP_CIPHER_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_aes_192_ctr) + return EVP_CIPHER_PTR(r0) +} + +var _mkcgo_EVP_aes_192_ecb uintptr + +func EVP_aes_192_ecb() EVP_CIPHER_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_aes_192_ecb) + return EVP_CIPHER_PTR(r0) +} + +var _mkcgo_EVP_aes_192_gcm uintptr + +func EVP_aes_192_gcm() EVP_CIPHER_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_aes_192_gcm) + return EVP_CIPHER_PTR(r0) +} + +var _mkcgo_EVP_aes_256_cbc uintptr + +func EVP_aes_256_cbc() EVP_CIPHER_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_aes_256_cbc) + return EVP_CIPHER_PTR(r0) +} + +var _mkcgo_EVP_aes_256_ctr uintptr + +func EVP_aes_256_ctr() EVP_CIPHER_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_aes_256_ctr) + return EVP_CIPHER_PTR(r0) +} + +var _mkcgo_EVP_aes_256_ecb uintptr + +func EVP_aes_256_ecb() EVP_CIPHER_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_aes_256_ecb) + return EVP_CIPHER_PTR(r0) +} + +var _mkcgo_EVP_aes_256_gcm uintptr + +func EVP_aes_256_gcm() EVP_CIPHER_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_aes_256_gcm) + return EVP_CIPHER_PTR(r0) +} + +var _mkcgo_EVP_default_properties_enable_fips uintptr + +func EVP_default_properties_enable_fips(libctx OSSL_LIB_CTX_PTR, enable int32) (int32, error) { + r0, _, _ := syscallN(_mkcgo_EVP_default_properties_enable_fips, uintptr(libctx), uintptr(enable)) + runtime.KeepAlive(libctx) + if int32(r0) <= 0 { + return 0, newMkcgoErr("EVP_default_properties_enable_fips", nil) + } + return int32(r0), nil +} + +var _mkcgo_EVP_default_properties_is_fips_enabled uintptr + +func EVP_default_properties_is_fips_enabled(libctx OSSL_LIB_CTX_PTR) int32 { + r0, _, _ := syscallN(_mkcgo_EVP_default_properties_is_fips_enabled, uintptr(libctx)) + runtime.KeepAlive(libctx) + return int32(r0) +} + +var _mkcgo_EVP_des_cbc uintptr + +func EVP_des_cbc() EVP_CIPHER_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_des_cbc) + return EVP_CIPHER_PTR(r0) +} + +var _mkcgo_EVP_des_ecb uintptr + +func EVP_des_ecb() EVP_CIPHER_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_des_ecb) + return EVP_CIPHER_PTR(r0) +} + +var _mkcgo_EVP_des_ede3_cbc uintptr + +func EVP_des_ede3_cbc() EVP_CIPHER_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_des_ede3_cbc) + return EVP_CIPHER_PTR(r0) +} + +var _mkcgo_EVP_des_ede3_ecb uintptr + +func EVP_des_ede3_ecb() EVP_CIPHER_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_des_ede3_ecb) + return EVP_CIPHER_PTR(r0) +} + +var _mkcgo_EVP_md4 uintptr + +func EVP_md4() EVP_MD_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_md4) + return EVP_MD_PTR(r0) +} + +var _mkcgo_EVP_md5 uintptr + +func EVP_md5() EVP_MD_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_md5) + return EVP_MD_PTR(r0) +} + +var _mkcgo_EVP_md5_sha1 uintptr + +func EVP_md5_sha1() EVP_MD_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_md5_sha1) + return EVP_MD_PTR(r0) +} + +var _mkcgo_EVP_rc4 uintptr + +func EVP_rc4() EVP_CIPHER_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_rc4) + return EVP_CIPHER_PTR(r0) +} + +var _mkcgo_EVP_ripemd160 uintptr + +func EVP_ripemd160() EVP_MD_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_ripemd160) + return EVP_MD_PTR(r0) +} + +var _mkcgo_EVP_sha1 uintptr + +func EVP_sha1() EVP_MD_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_sha1) + return EVP_MD_PTR(r0) +} + +var _mkcgo_EVP_sha224 uintptr + +func EVP_sha224() EVP_MD_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_sha224) + return EVP_MD_PTR(r0) +} + +var _mkcgo_EVP_sha256 uintptr + +func EVP_sha256() EVP_MD_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_sha256) + return EVP_MD_PTR(r0) +} + +var _mkcgo_EVP_sha384 uintptr + +func EVP_sha384() EVP_MD_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_sha384) + return EVP_MD_PTR(r0) +} + +var _mkcgo_EVP_sha3_224 uintptr + +func EVP_sha3_224() EVP_MD_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_sha3_224) + return EVP_MD_PTR(r0) +} + +var _mkcgo_EVP_sha3_256 uintptr + +func EVP_sha3_256() EVP_MD_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_sha3_256) + return EVP_MD_PTR(r0) +} + +var _mkcgo_EVP_sha3_384 uintptr + +func EVP_sha3_384() EVP_MD_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_sha3_384) + return EVP_MD_PTR(r0) +} + +var _mkcgo_EVP_sha3_512 uintptr + +func EVP_sha3_512() EVP_MD_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_sha3_512) + return EVP_MD_PTR(r0) +} + +var _mkcgo_EVP_sha512 uintptr + +func EVP_sha512() EVP_MD_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_sha512) + return EVP_MD_PTR(r0) +} + +var _mkcgo_EVP_sha512_224 uintptr + +func EVP_sha512_224() EVP_MD_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_sha512_224) + return EVP_MD_PTR(r0) +} + +var _mkcgo_EVP_sha512_256 uintptr + +func EVP_sha512_256() EVP_MD_PTR { + r0, _, _ := syscallN(_mkcgo_EVP_sha512_256) + return EVP_MD_PTR(r0) +} + +var _mkcgo_FIPS_mode uintptr + +func FIPS_mode() int32 { + r0, _, _ := syscallN(_mkcgo_FIPS_mode) + return int32(r0) +} + +var _mkcgo_FIPS_mode_set uintptr + +func FIPS_mode_set(r int32) (int32, error) { + r0, _, _ := syscallN(_mkcgo_FIPS_mode_set, uintptr(r)) + if int32(r0) <= 0 { + return 0, newMkcgoErr("FIPS_mode_set", nil) + } + return int32(r0), nil +} + +var _mkcgo_HMAC_CTX_copy uintptr + +func HMAC_CTX_copy(dest HMAC_CTX_PTR, src HMAC_CTX_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_HMAC_CTX_copy, uintptr(dest), uintptr(src)) + runtime.KeepAlive(dest) + runtime.KeepAlive(src) + if int32(r0) <= 0 { + return 0, newMkcgoErr("HMAC_CTX_copy", nil) + } + return int32(r0), nil +} + +var _mkcgo_HMAC_CTX_free uintptr + +func HMAC_CTX_free(arg0 HMAC_CTX_PTR) { + syscallN(_mkcgo_HMAC_CTX_free, uintptr(arg0)) + runtime.KeepAlive(arg0) +} + +var _mkcgo_HMAC_CTX_new uintptr + +func HMAC_CTX_new() (HMAC_CTX_PTR, error) { + r0, _, _ := syscallN(_mkcgo_HMAC_CTX_new) + if HMAC_CTX_PTR(r0) == nil { + return nil, newMkcgoErr("HMAC_CTX_new", nil) + } + return HMAC_CTX_PTR(r0), nil +} + +var _mkcgo_HMAC_Final uintptr + +func HMAC_Final(arg0 HMAC_CTX_PTR, arg1 *byte, arg2 *uint32) (int32, error) { + r0, _, _ := syscallN(_mkcgo_HMAC_Final, uintptr(arg0), uintptr(unsafe.Pointer(arg1)), uintptr(unsafe.Pointer(arg2))) + runtime.KeepAlive(arg0) + runtime.KeepAlive(arg1) + runtime.KeepAlive(arg2) + if int32(r0) <= 0 { + return 0, newMkcgoErr("HMAC_Final", nil) + } + return int32(r0), nil +} + +var _mkcgo_HMAC_Init_ex uintptr + +func HMAC_Init_ex(arg0 HMAC_CTX_PTR, arg1 unsafe.Pointer, arg2 int32, arg3 EVP_MD_PTR, arg4 ENGINE_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_HMAC_Init_ex, uintptr(arg0), uintptr(arg1), uintptr(arg2), uintptr(arg3), uintptr(arg4)) + runtime.KeepAlive(arg0) + runtime.KeepAlive(arg3) + runtime.KeepAlive(arg4) + if int32(r0) <= 0 { + return 0, newMkcgoErr("HMAC_Init_ex", nil) + } + return int32(r0), nil +} + +var _mkcgo_HMAC_Update uintptr + +func HMAC_Update(arg0 HMAC_CTX_PTR, arg1 *byte, arg2 int) (int32, error) { + r0, _, _ := syscallN(_mkcgo_HMAC_Update, uintptr(arg0), uintptr(unsafe.Pointer(arg1)), uintptr(arg2)) + runtime.KeepAlive(arg0) + runtime.KeepAlive(arg1) + if int32(r0) <= 0 { + return 0, newMkcgoErr("HMAC_Update", nil) + } + return int32(r0), nil +} + +var _mkcgo_OBJ_nid2sn uintptr + +func OBJ_nid2sn(n int32) *byte { + r0, _, _ := syscallN(_mkcgo_OBJ_nid2sn, uintptr(n)) + return (*byte)(unsafe.Pointer(r0)) +} + +var _mkcgo_OPENSSL_init uintptr + +func OPENSSL_init() { + syscallN(_mkcgo_OPENSSL_init) +} + +var _mkcgo_OPENSSL_init_crypto uintptr + +func OPENSSL_init_crypto(ops uint64, settings OPENSSL_INIT_SETTINGS_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_OPENSSL_init_crypto, uintptr(ops), uintptr(settings)) + runtime.KeepAlive(settings) + if int32(r0) <= 0 { + return 0, newMkcgoErr("OPENSSL_init_crypto", nil) + } + return int32(r0), nil +} + +func OPENSSL_version_major_Available() bool { + return _mkcgo_OPENSSL_version_major != 0 +} + +var _mkcgo_OPENSSL_version_major uintptr + +func OPENSSL_version_major() uint32 { + r0, _, _ := syscallN(_mkcgo_OPENSSL_version_major) + return uint32(r0) +} + +func OPENSSL_version_minor_Available() bool { + return _mkcgo_OPENSSL_version_minor != 0 +} + +var _mkcgo_OPENSSL_version_minor uintptr + +func OPENSSL_version_minor() uint32 { + r0, _, _ := syscallN(_mkcgo_OPENSSL_version_minor) + return uint32(r0) +} + +func OPENSSL_version_patch_Available() bool { + return _mkcgo_OPENSSL_version_patch != 0 +} + +var _mkcgo_OPENSSL_version_patch uintptr + +func OPENSSL_version_patch() uint32 { + r0, _, _ := syscallN(_mkcgo_OPENSSL_version_patch) + return uint32(r0) +} + +var _mkcgo_OSSL_PARAM_BLD_free uintptr + +func OSSL_PARAM_BLD_free(bld OSSL_PARAM_BLD_PTR) { + syscallN(_mkcgo_OSSL_PARAM_BLD_free, uintptr(bld)) + runtime.KeepAlive(bld) +} + +var _mkcgo_OSSL_PARAM_BLD_new uintptr + +func OSSL_PARAM_BLD_new() (OSSL_PARAM_BLD_PTR, error) { + r0, _, _ := syscallN(_mkcgo_OSSL_PARAM_BLD_new) + if OSSL_PARAM_BLD_PTR(r0) == nil { + return nil, newMkcgoErr("OSSL_PARAM_BLD_new", nil) + } + return OSSL_PARAM_BLD_PTR(r0), nil +} + +var _mkcgo_OSSL_PARAM_BLD_push_BN uintptr + +func OSSL_PARAM_BLD_push_BN(bld OSSL_PARAM_BLD_PTR, key *byte, bn BIGNUM_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_OSSL_PARAM_BLD_push_BN, uintptr(bld), uintptr(unsafe.Pointer(key)), uintptr(bn)) + runtime.KeepAlive(bld) + runtime.KeepAlive(key) + runtime.KeepAlive(bn) + if int32(r0) <= 0 { + return 0, newMkcgoErr("OSSL_PARAM_BLD_push_BN", nil) + } + return int32(r0), nil +} + +var _mkcgo_OSSL_PARAM_BLD_push_int32 uintptr + +func OSSL_PARAM_BLD_push_int32(bld OSSL_PARAM_BLD_PTR, key *byte, num int32) (int32, error) { + r0, _, _ := syscallN(_mkcgo_OSSL_PARAM_BLD_push_int32, uintptr(bld), uintptr(unsafe.Pointer(key)), uintptr(num)) + runtime.KeepAlive(bld) + runtime.KeepAlive(key) + if int32(r0) <= 0 { + return 0, newMkcgoErr("OSSL_PARAM_BLD_push_int32", nil) + } + return int32(r0), nil +} + +var _mkcgo_OSSL_PARAM_BLD_push_octet_string uintptr + +func OSSL_PARAM_BLD_push_octet_string(bld OSSL_PARAM_BLD_PTR, key *byte, buf unsafe.Pointer, bsize int) (int32, error) { + r0, _, _ := syscallN(_mkcgo_OSSL_PARAM_BLD_push_octet_string, uintptr(bld), uintptr(unsafe.Pointer(key)), uintptr(buf), uintptr(bsize)) + runtime.KeepAlive(bld) + runtime.KeepAlive(key) + if int32(r0) <= 0 { + return 0, newMkcgoErr("OSSL_PARAM_BLD_push_octet_string", nil) + } + return int32(r0), nil +} + +var _mkcgo_OSSL_PARAM_BLD_push_utf8_string uintptr + +func OSSL_PARAM_BLD_push_utf8_string(bld OSSL_PARAM_BLD_PTR, key *byte, buf *byte, bsize int) (int32, error) { + r0, _, _ := syscallN(_mkcgo_OSSL_PARAM_BLD_push_utf8_string, uintptr(bld), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(buf)), uintptr(bsize)) + runtime.KeepAlive(bld) + runtime.KeepAlive(key) + runtime.KeepAlive(buf) + if int32(r0) <= 0 { + return 0, newMkcgoErr("OSSL_PARAM_BLD_push_utf8_string", nil) + } + return int32(r0), nil +} + +var _mkcgo_OSSL_PARAM_BLD_to_param uintptr + +func OSSL_PARAM_BLD_to_param(bld OSSL_PARAM_BLD_PTR) (OSSL_PARAM_PTR, error) { + r0, _, _ := syscallN(_mkcgo_OSSL_PARAM_BLD_to_param, uintptr(bld)) + runtime.KeepAlive(bld) + if OSSL_PARAM_PTR(r0) == nil { + return nil, newMkcgoErr("OSSL_PARAM_BLD_to_param", nil) + } + return OSSL_PARAM_PTR(r0), nil +} + +var _mkcgo_OSSL_PARAM_free uintptr + +func OSSL_PARAM_free(p OSSL_PARAM_PTR) { + syscallN(_mkcgo_OSSL_PARAM_free, uintptr(p)) + runtime.KeepAlive(p) +} + +var _mkcgo_OSSL_PARAM_locate_const uintptr + +func OSSL_PARAM_locate_const(p OSSL_PARAM_PTR, key *byte) (OSSL_PARAM_PTR, error) { + r0, _, _ := syscallN(_mkcgo_OSSL_PARAM_locate_const, uintptr(p), uintptr(unsafe.Pointer(key))) + runtime.KeepAlive(p) + runtime.KeepAlive(key) + if OSSL_PARAM_PTR(r0) == nil { + return nil, newMkcgoErr("OSSL_PARAM_locate_const", nil) + } + return OSSL_PARAM_PTR(r0), nil +} + +var _mkcgo_OSSL_PROVIDER_available uintptr + +func OSSL_PROVIDER_available(libctx OSSL_LIB_CTX_PTR, name *byte) int32 { + r0, _, _ := syscallN(_mkcgo_OSSL_PROVIDER_available, uintptr(libctx), uintptr(unsafe.Pointer(name))) + runtime.KeepAlive(libctx) + runtime.KeepAlive(name) + return int32(r0) +} + +var _mkcgo_OSSL_PROVIDER_get0_name uintptr + +func OSSL_PROVIDER_get0_name(prov OSSL_PROVIDER_PTR) *byte { + r0, _, _ := syscallN(_mkcgo_OSSL_PROVIDER_get0_name, uintptr(prov)) + runtime.KeepAlive(prov) + return (*byte)(unsafe.Pointer(r0)) +} + +var _mkcgo_OSSL_PROVIDER_try_load uintptr + +func OSSL_PROVIDER_try_load(libctx OSSL_LIB_CTX_PTR, name *byte, retain_fallbacks int32) (OSSL_PROVIDER_PTR, error) { + r0, _, _ := syscallN(_mkcgo_OSSL_PROVIDER_try_load, uintptr(libctx), uintptr(unsafe.Pointer(name)), uintptr(retain_fallbacks)) + runtime.KeepAlive(libctx) + runtime.KeepAlive(name) + if OSSL_PROVIDER_PTR(r0) == nil { + return nil, newMkcgoErr("OSSL_PROVIDER_try_load", nil) + } + return OSSL_PROVIDER_PTR(r0), nil +} + +var _mkcgo_OpenSSL_version uintptr + +func OpenSSL_version(__type int32) *byte { + r0, _, _ := syscallN(_mkcgo_OpenSSL_version, uintptr(__type)) + return (*byte)(unsafe.Pointer(r0)) +} + +func OpenSSL_version_num_Available() bool { + return _mkcgo_OpenSSL_version_num != 0 +} + +var _mkcgo_OpenSSL_version_num uintptr + +func OpenSSL_version_num() uint64 { + r0, _, _ := syscallN(_mkcgo_OpenSSL_version_num) + return uint64(r0) +} + +var _mkcgo_PKCS5_PBKDF2_HMAC uintptr + +func PKCS5_PBKDF2_HMAC(pass *byte, passlen int32, salt *byte, saltlen int32, iter int32, digest EVP_MD_PTR, keylen int32, out *byte) (int32, error) { + r0, _, _ := syscallN(_mkcgo_PKCS5_PBKDF2_HMAC, uintptr(unsafe.Pointer(pass)), uintptr(passlen), uintptr(unsafe.Pointer(salt)), uintptr(saltlen), uintptr(iter), uintptr(digest), uintptr(keylen), uintptr(unsafe.Pointer(out))) + runtime.KeepAlive(pass) + runtime.KeepAlive(salt) + runtime.KeepAlive(digest) + runtime.KeepAlive(out) + if int32(r0) <= 0 { + return 0, newMkcgoErr("PKCS5_PBKDF2_HMAC", nil) + } + return int32(r0), nil +} + +var _mkcgo_RAND_bytes uintptr + +func RAND_bytes(arg0 *byte, arg1 int32) (int32, error) { + r0, _, _ := syscallN(_mkcgo_RAND_bytes, uintptr(unsafe.Pointer(arg0)), uintptr(arg1)) + runtime.KeepAlive(arg0) + if int32(r0) <= 0 { + return 0, newMkcgoErr("RAND_bytes", nil) + } + return int32(r0), nil +} + +var _mkcgo_RSA_free uintptr + +func RSA_free(arg0 RSA_PTR) { + syscallN(_mkcgo_RSA_free, uintptr(arg0)) + runtime.KeepAlive(arg0) +} + +var _mkcgo_RSA_get0_crt_params uintptr + +func RSA_get0_crt_params(r RSA_PTR, dmp1 *BIGNUM_PTR, dmq1 *BIGNUM_PTR, iqmp *BIGNUM_PTR) { + syscallN(_mkcgo_RSA_get0_crt_params, uintptr(r), uintptr(unsafe.Pointer(dmp1)), uintptr(unsafe.Pointer(dmq1)), uintptr(unsafe.Pointer(iqmp))) + runtime.KeepAlive(r) + runtime.KeepAlive(dmp1) + runtime.KeepAlive(dmq1) + runtime.KeepAlive(iqmp) +} + +var _mkcgo_RSA_get0_factors uintptr + +func RSA_get0_factors(rsa RSA_PTR, p *BIGNUM_PTR, q *BIGNUM_PTR) { + syscallN(_mkcgo_RSA_get0_factors, uintptr(rsa), uintptr(unsafe.Pointer(p)), uintptr(unsafe.Pointer(q))) + runtime.KeepAlive(rsa) + runtime.KeepAlive(p) + runtime.KeepAlive(q) +} + +var _mkcgo_RSA_get0_key uintptr + +func RSA_get0_key(rsa RSA_PTR, n *BIGNUM_PTR, e *BIGNUM_PTR, d *BIGNUM_PTR) { + syscallN(_mkcgo_RSA_get0_key, uintptr(rsa), uintptr(unsafe.Pointer(n)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(d))) + runtime.KeepAlive(rsa) + runtime.KeepAlive(n) + runtime.KeepAlive(e) + runtime.KeepAlive(d) +} + +var _mkcgo_RSA_new uintptr + +func RSA_new() (RSA_PTR, error) { + r0, _, _ := syscallN(_mkcgo_RSA_new) + if RSA_PTR(r0) == nil { + return nil, newMkcgoErr("RSA_new", nil) + } + return RSA_PTR(r0), nil +} + +var _mkcgo_RSA_set0_crt_params uintptr + +func RSA_set0_crt_params(rsa RSA_PTR, dmp1 BIGNUM_PTR, dmp2 BIGNUM_PTR, iqmp BIGNUM_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_RSA_set0_crt_params, uintptr(rsa), uintptr(dmp1), uintptr(dmp2), uintptr(iqmp)) + runtime.KeepAlive(rsa) + runtime.KeepAlive(dmp1) + runtime.KeepAlive(dmp2) + runtime.KeepAlive(iqmp) + if int32(r0) <= 0 { + return 0, newMkcgoErr("RSA_set0_crt_params", nil) + } + return int32(r0), nil +} + +var _mkcgo_RSA_set0_factors uintptr + +func RSA_set0_factors(rsa RSA_PTR, p BIGNUM_PTR, q BIGNUM_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_RSA_set0_factors, uintptr(rsa), uintptr(p), uintptr(q)) + runtime.KeepAlive(rsa) + runtime.KeepAlive(p) + runtime.KeepAlive(q) + if int32(r0) <= 0 { + return 0, newMkcgoErr("RSA_set0_factors", nil) + } + return int32(r0), nil +} + +var _mkcgo_RSA_set0_key uintptr + +func RSA_set0_key(r RSA_PTR, n BIGNUM_PTR, e BIGNUM_PTR, d BIGNUM_PTR) (int32, error) { + r0, _, _ := syscallN(_mkcgo_RSA_set0_key, uintptr(r), uintptr(n), uintptr(e), uintptr(d)) + runtime.KeepAlive(r) + runtime.KeepAlive(n) + runtime.KeepAlive(e) + runtime.KeepAlive(d) + if int32(r0) <= 0 { + return 0, newMkcgoErr("RSA_set0_key", nil) + } + return int32(r0), nil +} + +func MkcgoLoad_(handle unsafe.Pointer) { + _mkcgo_BN_bin2bn = dlsym(handle, "BN_bin2bn\x00", false) + _mkcgo_BN_bn2binpad = dlsym(handle, "BN_bn2binpad\x00", false) + _mkcgo_BN_bn2lebinpad = dlsym(handle, "BN_bn2lebinpad\x00", false) + _mkcgo_BN_clear = dlsym(handle, "BN_clear\x00", false) + _mkcgo_BN_clear_free = dlsym(handle, "BN_clear_free\x00", false) + _mkcgo_BN_free = dlsym(handle, "BN_free\x00", false) + _mkcgo_BN_lebin2bn = dlsym(handle, "BN_lebin2bn\x00", false) + _mkcgo_BN_new = dlsym(handle, "BN_new\x00", false) + _mkcgo_BN_num_bits = dlsym(handle, "BN_num_bits\x00", false) + _mkcgo_CRYPTO_free = dlsym(handle, "CRYPTO_free\x00", false) + _mkcgo_CRYPTO_malloc = dlsym(handle, "CRYPTO_malloc\x00", false) + _mkcgo_EC_GROUP_free = dlsym(handle, "EC_GROUP_free\x00", false) + _mkcgo_EC_GROUP_new_by_curve_name = dlsym(handle, "EC_GROUP_new_by_curve_name\x00", false) + _mkcgo_EC_POINT_free = dlsym(handle, "EC_POINT_free\x00", false) + _mkcgo_EC_POINT_mul = dlsym(handle, "EC_POINT_mul\x00", false) + _mkcgo_EC_POINT_new = dlsym(handle, "EC_POINT_new\x00", false) + _mkcgo_EC_POINT_oct2point = dlsym(handle, "EC_POINT_oct2point\x00", false) + _mkcgo_EC_POINT_point2oct = dlsym(handle, "EC_POINT_point2oct\x00", false) + _mkcgo_ERR_clear_error = dlsym(handle, "ERR_clear_error\x00", false) + _mkcgo_ERR_error_string_n = dlsym(handle, "ERR_error_string_n\x00", false) + _mkcgo_EVP_CIPHER_CTX_ctrl = dlsym(handle, "EVP_CIPHER_CTX_ctrl\x00", false) + _mkcgo_EVP_CIPHER_CTX_free = dlsym(handle, "EVP_CIPHER_CTX_free\x00", false) + _mkcgo_EVP_CIPHER_CTX_new = dlsym(handle, "EVP_CIPHER_CTX_new\x00", false) + _mkcgo_EVP_CIPHER_CTX_set_key_length = dlsym(handle, "EVP_CIPHER_CTX_set_key_length\x00", false) + _mkcgo_EVP_CIPHER_CTX_set_padding = dlsym(handle, "EVP_CIPHER_CTX_set_padding\x00", false) + _mkcgo_EVP_CipherInit_ex = dlsym(handle, "EVP_CipherInit_ex\x00", false) + _mkcgo_EVP_CipherUpdate = dlsym(handle, "EVP_CipherUpdate\x00", false) + _mkcgo_EVP_DecryptFinal_ex = dlsym(handle, "EVP_DecryptFinal_ex\x00", false) + _mkcgo_EVP_DecryptInit_ex = dlsym(handle, "EVP_DecryptInit_ex\x00", false) + _mkcgo_EVP_DecryptUpdate = dlsym(handle, "EVP_DecryptUpdate\x00", false) + _mkcgo_EVP_Digest = dlsym(handle, "EVP_Digest\x00", false) + _mkcgo_EVP_DigestFinal_ex = dlsym(handle, "EVP_DigestFinal_ex\x00", false) + _mkcgo_EVP_DigestInit = dlsym(handle, "EVP_DigestInit\x00", false) + _mkcgo_EVP_DigestInit_ex = dlsym(handle, "EVP_DigestInit_ex\x00", false) + _mkcgo_EVP_DigestSignFinal = dlsym(handle, "EVP_DigestSignFinal\x00", false) + _mkcgo_EVP_DigestSignInit = dlsym(handle, "EVP_DigestSignInit\x00", false) + _mkcgo_EVP_DigestUpdate = dlsym(handle, "EVP_DigestUpdate\x00", false) + _mkcgo_EVP_DigestVerifyFinal = dlsym(handle, "EVP_DigestVerifyFinal\x00", false) + _mkcgo_EVP_DigestVerifyInit = dlsym(handle, "EVP_DigestVerifyInit\x00", false) + _mkcgo_EVP_EncryptFinal_ex = dlsym(handle, "EVP_EncryptFinal_ex\x00", false) + _mkcgo_EVP_EncryptInit_ex = dlsym(handle, "EVP_EncryptInit_ex\x00", false) + _mkcgo_EVP_EncryptUpdate = dlsym(handle, "EVP_EncryptUpdate\x00", false) + _mkcgo_EVP_MD_CTX_copy = dlsym(handle, "EVP_MD_CTX_copy\x00", false) + _mkcgo_EVP_MD_CTX_copy_ex = dlsym(handle, "EVP_MD_CTX_copy_ex\x00", false) + _mkcgo_EVP_MD_CTX_free = dlsym(handle, "EVP_MD_CTX_free\x00", false) + _mkcgo_EVP_MD_CTX_new = dlsym(handle, "EVP_MD_CTX_new\x00", false) + _mkcgo_EVP_PKEY_CTX_ctrl = dlsym(handle, "EVP_PKEY_CTX_ctrl\x00", false) + _mkcgo_EVP_PKEY_CTX_free = dlsym(handle, "EVP_PKEY_CTX_free\x00", false) + _mkcgo_EVP_PKEY_CTX_new = dlsym(handle, "EVP_PKEY_CTX_new\x00", false) + _mkcgo_EVP_PKEY_CTX_new_id = dlsym(handle, "EVP_PKEY_CTX_new_id\x00", false) + _mkcgo_EVP_PKEY_decrypt = dlsym(handle, "EVP_PKEY_decrypt\x00", false) + _mkcgo_EVP_PKEY_decrypt_init = dlsym(handle, "EVP_PKEY_decrypt_init\x00", false) + _mkcgo_EVP_PKEY_derive = dlsym(handle, "EVP_PKEY_derive\x00", false) + _mkcgo_EVP_PKEY_derive_init = dlsym(handle, "EVP_PKEY_derive_init\x00", false) + _mkcgo_EVP_PKEY_derive_set_peer = dlsym(handle, "EVP_PKEY_derive_set_peer\x00", false) + _mkcgo_EVP_PKEY_encrypt = dlsym(handle, "EVP_PKEY_encrypt\x00", false) + _mkcgo_EVP_PKEY_encrypt_init = dlsym(handle, "EVP_PKEY_encrypt_init\x00", false) + _mkcgo_EVP_PKEY_free = dlsym(handle, "EVP_PKEY_free\x00", false) + _mkcgo_EVP_PKEY_keygen = dlsym(handle, "EVP_PKEY_keygen\x00", false) + _mkcgo_EVP_PKEY_keygen_init = dlsym(handle, "EVP_PKEY_keygen_init\x00", false) + _mkcgo_EVP_PKEY_new = dlsym(handle, "EVP_PKEY_new\x00", false) + _mkcgo_EVP_PKEY_paramgen = dlsym(handle, "EVP_PKEY_paramgen\x00", false) + _mkcgo_EVP_PKEY_paramgen_init = dlsym(handle, "EVP_PKEY_paramgen_init\x00", false) + _mkcgo_EVP_PKEY_sign = dlsym(handle, "EVP_PKEY_sign\x00", false) + _mkcgo_EVP_PKEY_sign_init = dlsym(handle, "EVP_PKEY_sign_init\x00", false) + _mkcgo_EVP_PKEY_verify = dlsym(handle, "EVP_PKEY_verify\x00", false) + _mkcgo_EVP_PKEY_verify_init = dlsym(handle, "EVP_PKEY_verify_init\x00", false) + _mkcgo_EVP_aes_128_cbc = dlsym(handle, "EVP_aes_128_cbc\x00", false) + _mkcgo_EVP_aes_128_ctr = dlsym(handle, "EVP_aes_128_ctr\x00", false) + _mkcgo_EVP_aes_128_ecb = dlsym(handle, "EVP_aes_128_ecb\x00", false) + _mkcgo_EVP_aes_128_gcm = dlsym(handle, "EVP_aes_128_gcm\x00", false) + _mkcgo_EVP_aes_192_cbc = dlsym(handle, "EVP_aes_192_cbc\x00", false) + _mkcgo_EVP_aes_192_ctr = dlsym(handle, "EVP_aes_192_ctr\x00", false) + _mkcgo_EVP_aes_192_ecb = dlsym(handle, "EVP_aes_192_ecb\x00", false) + _mkcgo_EVP_aes_192_gcm = dlsym(handle, "EVP_aes_192_gcm\x00", false) + _mkcgo_EVP_aes_256_cbc = dlsym(handle, "EVP_aes_256_cbc\x00", false) + _mkcgo_EVP_aes_256_ctr = dlsym(handle, "EVP_aes_256_ctr\x00", false) + _mkcgo_EVP_aes_256_ecb = dlsym(handle, "EVP_aes_256_ecb\x00", false) + _mkcgo_EVP_aes_256_gcm = dlsym(handle, "EVP_aes_256_gcm\x00", false) + _mkcgo_EVP_des_cbc = dlsym(handle, "EVP_des_cbc\x00", false) + _mkcgo_EVP_des_ecb = dlsym(handle, "EVP_des_ecb\x00", false) + _mkcgo_EVP_des_ede3_cbc = dlsym(handle, "EVP_des_ede3_cbc\x00", false) + _mkcgo_EVP_des_ede3_ecb = dlsym(handle, "EVP_des_ede3_ecb\x00", false) + _mkcgo_EVP_md4 = dlsym(handle, "EVP_md4\x00", false) + _mkcgo_EVP_md5 = dlsym(handle, "EVP_md5\x00", false) + _mkcgo_EVP_md5_sha1 = dlsym(handle, "EVP_md5_sha1\x00", false) + _mkcgo_EVP_rc4 = dlsym(handle, "EVP_rc4\x00", false) + _mkcgo_EVP_ripemd160 = dlsym(handle, "EVP_ripemd160\x00", false) + _mkcgo_EVP_sha1 = dlsym(handle, "EVP_sha1\x00", false) + _mkcgo_EVP_sha224 = dlsym(handle, "EVP_sha224\x00", false) + _mkcgo_EVP_sha256 = dlsym(handle, "EVP_sha256\x00", false) + _mkcgo_EVP_sha384 = dlsym(handle, "EVP_sha384\x00", false) + _mkcgo_EVP_sha512 = dlsym(handle, "EVP_sha512\x00", false) + _mkcgo_OBJ_nid2sn = dlsym(handle, "OBJ_nid2sn\x00", false) + _mkcgo_OPENSSL_init = dlsym(handle, "OPENSSL_init\x00", false) + _mkcgo_OPENSSL_init_crypto = dlsym(handle, "OPENSSL_init_crypto\x00", false) + _mkcgo_OpenSSL_version = dlsym(handle, "OpenSSL_version\x00", false) + _mkcgo_PKCS5_PBKDF2_HMAC = dlsym(handle, "PKCS5_PBKDF2_HMAC\x00", false) + _mkcgo_RAND_bytes = dlsym(handle, "RAND_bytes\x00", false) +} + +func MkcgoUnload_() { + _mkcgo_BN_bin2bn = 0 + _mkcgo_BN_bn2binpad = 0 + _mkcgo_BN_bn2lebinpad = 0 + _mkcgo_BN_clear = 0 + _mkcgo_BN_clear_free = 0 + _mkcgo_BN_free = 0 + _mkcgo_BN_lebin2bn = 0 + _mkcgo_BN_new = 0 + _mkcgo_BN_num_bits = 0 + _mkcgo_CRYPTO_free = 0 + _mkcgo_CRYPTO_malloc = 0 + _mkcgo_EC_GROUP_free = 0 + _mkcgo_EC_GROUP_new_by_curve_name = 0 + _mkcgo_EC_POINT_free = 0 + _mkcgo_EC_POINT_mul = 0 + _mkcgo_EC_POINT_new = 0 + _mkcgo_EC_POINT_oct2point = 0 + _mkcgo_EC_POINT_point2oct = 0 + _mkcgo_ERR_clear_error = 0 + _mkcgo_ERR_error_string_n = 0 + _mkcgo_EVP_CIPHER_CTX_ctrl = 0 + _mkcgo_EVP_CIPHER_CTX_free = 0 + _mkcgo_EVP_CIPHER_CTX_new = 0 + _mkcgo_EVP_CIPHER_CTX_set_key_length = 0 + _mkcgo_EVP_CIPHER_CTX_set_padding = 0 + _mkcgo_EVP_CipherInit_ex = 0 + _mkcgo_EVP_CipherUpdate = 0 + _mkcgo_EVP_DecryptFinal_ex = 0 + _mkcgo_EVP_DecryptInit_ex = 0 + _mkcgo_EVP_DecryptUpdate = 0 + _mkcgo_EVP_Digest = 0 + _mkcgo_EVP_DigestFinal_ex = 0 + _mkcgo_EVP_DigestInit = 0 + _mkcgo_EVP_DigestInit_ex = 0 + _mkcgo_EVP_DigestSignFinal = 0 + _mkcgo_EVP_DigestSignInit = 0 + _mkcgo_EVP_DigestUpdate = 0 + _mkcgo_EVP_DigestVerifyFinal = 0 + _mkcgo_EVP_DigestVerifyInit = 0 + _mkcgo_EVP_EncryptFinal_ex = 0 + _mkcgo_EVP_EncryptInit_ex = 0 + _mkcgo_EVP_EncryptUpdate = 0 + _mkcgo_EVP_MD_CTX_copy = 0 + _mkcgo_EVP_MD_CTX_copy_ex = 0 + _mkcgo_EVP_MD_CTX_free = 0 + _mkcgo_EVP_MD_CTX_new = 0 + _mkcgo_EVP_PKEY_CTX_ctrl = 0 + _mkcgo_EVP_PKEY_CTX_free = 0 + _mkcgo_EVP_PKEY_CTX_new = 0 + _mkcgo_EVP_PKEY_CTX_new_id = 0 + _mkcgo_EVP_PKEY_decrypt = 0 + _mkcgo_EVP_PKEY_decrypt_init = 0 + _mkcgo_EVP_PKEY_derive = 0 + _mkcgo_EVP_PKEY_derive_init = 0 + _mkcgo_EVP_PKEY_derive_set_peer = 0 + _mkcgo_EVP_PKEY_encrypt = 0 + _mkcgo_EVP_PKEY_encrypt_init = 0 + _mkcgo_EVP_PKEY_free = 0 + _mkcgo_EVP_PKEY_keygen = 0 + _mkcgo_EVP_PKEY_keygen_init = 0 + _mkcgo_EVP_PKEY_new = 0 + _mkcgo_EVP_PKEY_paramgen = 0 + _mkcgo_EVP_PKEY_paramgen_init = 0 + _mkcgo_EVP_PKEY_sign = 0 + _mkcgo_EVP_PKEY_sign_init = 0 + _mkcgo_EVP_PKEY_verify = 0 + _mkcgo_EVP_PKEY_verify_init = 0 + _mkcgo_EVP_aes_128_cbc = 0 + _mkcgo_EVP_aes_128_ctr = 0 + _mkcgo_EVP_aes_128_ecb = 0 + _mkcgo_EVP_aes_128_gcm = 0 + _mkcgo_EVP_aes_192_cbc = 0 + _mkcgo_EVP_aes_192_ctr = 0 + _mkcgo_EVP_aes_192_ecb = 0 + _mkcgo_EVP_aes_192_gcm = 0 + _mkcgo_EVP_aes_256_cbc = 0 + _mkcgo_EVP_aes_256_ctr = 0 + _mkcgo_EVP_aes_256_ecb = 0 + _mkcgo_EVP_aes_256_gcm = 0 + _mkcgo_EVP_des_cbc = 0 + _mkcgo_EVP_des_ecb = 0 + _mkcgo_EVP_des_ede3_cbc = 0 + _mkcgo_EVP_des_ede3_ecb = 0 + _mkcgo_EVP_md4 = 0 + _mkcgo_EVP_md5 = 0 + _mkcgo_EVP_md5_sha1 = 0 + _mkcgo_EVP_rc4 = 0 + _mkcgo_EVP_ripemd160 = 0 + _mkcgo_EVP_sha1 = 0 + _mkcgo_EVP_sha224 = 0 + _mkcgo_EVP_sha256 = 0 + _mkcgo_EVP_sha384 = 0 + _mkcgo_EVP_sha512 = 0 + _mkcgo_OBJ_nid2sn = 0 + _mkcgo_OPENSSL_init = 0 + _mkcgo_OPENSSL_init_crypto = 0 + _mkcgo_OpenSSL_version = 0 + _mkcgo_PKCS5_PBKDF2_HMAC = 0 + _mkcgo_RAND_bytes = 0 +} + +func MkcgoLoad_111(handle unsafe.Pointer) { + _mkcgo_EVP_DigestSign = dlsym(handle, "EVP_DigestSign\x00", false) + _mkcgo_EVP_DigestVerify = dlsym(handle, "EVP_DigestVerify\x00", false) + _mkcgo_EVP_PKEY_get_raw_private_key = dlsym(handle, "EVP_PKEY_get_raw_private_key\x00", false) + _mkcgo_EVP_PKEY_get_raw_public_key = dlsym(handle, "EVP_PKEY_get_raw_public_key\x00", false) + _mkcgo_EVP_PKEY_new_raw_private_key = dlsym(handle, "EVP_PKEY_new_raw_private_key\x00", false) + _mkcgo_EVP_PKEY_new_raw_public_key = dlsym(handle, "EVP_PKEY_new_raw_public_key\x00", false) + _mkcgo_EVP_sha3_224 = dlsym(handle, "EVP_sha3_224\x00", false) + _mkcgo_EVP_sha3_256 = dlsym(handle, "EVP_sha3_256\x00", false) + _mkcgo_EVP_sha3_384 = dlsym(handle, "EVP_sha3_384\x00", false) + _mkcgo_EVP_sha3_512 = dlsym(handle, "EVP_sha3_512\x00", false) + _mkcgo_EVP_sha512_224 = dlsym(handle, "EVP_sha512_224\x00", false) + _mkcgo_EVP_sha512_256 = dlsym(handle, "EVP_sha512_256\x00", false) +} + +func MkcgoUnload_111() { + _mkcgo_EVP_DigestSign = 0 + _mkcgo_EVP_DigestVerify = 0 + _mkcgo_EVP_PKEY_get_raw_private_key = 0 + _mkcgo_EVP_PKEY_get_raw_public_key = 0 + _mkcgo_EVP_PKEY_new_raw_private_key = 0 + _mkcgo_EVP_PKEY_new_raw_public_key = 0 + _mkcgo_EVP_sha3_224 = 0 + _mkcgo_EVP_sha3_256 = 0 + _mkcgo_EVP_sha3_384 = 0 + _mkcgo_EVP_sha3_512 = 0 + _mkcgo_EVP_sha512_224 = 0 + _mkcgo_EVP_sha512_256 = 0 +} + +func MkcgoLoad_3(handle unsafe.Pointer) { + _mkcgo_EC_POINT_set_affine_coordinates = dlsym(handle, "EC_POINT_set_affine_coordinates\x00", false) + _mkcgo_ERR_get_error_all = dlsym(handle, "ERR_get_error_all\x00", false) + _mkcgo_EVP_CIPHER_fetch = dlsym(handle, "EVP_CIPHER_fetch\x00", false) + _mkcgo_EVP_CIPHER_get0_name = dlsym(handle, "EVP_CIPHER_get0_name\x00", false) + _mkcgo_EVP_CIPHER_get_block_size = dlsym(handle, "EVP_CIPHER_get_block_size\x00", false) + _mkcgo_EVP_KDF_CTX_free = dlsym(handle, "EVP_KDF_CTX_free\x00", false) + _mkcgo_EVP_KDF_CTX_get_kdf_size = dlsym(handle, "EVP_KDF_CTX_get_kdf_size\x00", false) + _mkcgo_EVP_KDF_CTX_new = dlsym(handle, "EVP_KDF_CTX_new\x00", false) + _mkcgo_EVP_KDF_CTX_set_params = dlsym(handle, "EVP_KDF_CTX_set_params\x00", false) + _mkcgo_EVP_KDF_derive = dlsym(handle, "EVP_KDF_derive\x00", false) + _mkcgo_EVP_KDF_fetch = dlsym(handle, "EVP_KDF_fetch\x00", false) + _mkcgo_EVP_KDF_free = dlsym(handle, "EVP_KDF_free\x00", false) + _mkcgo_EVP_MAC_CTX_dup = dlsym(handle, "EVP_MAC_CTX_dup\x00", false) + _mkcgo_EVP_MAC_CTX_free = dlsym(handle, "EVP_MAC_CTX_free\x00", false) + _mkcgo_EVP_MAC_CTX_new = dlsym(handle, "EVP_MAC_CTX_new\x00", false) + _mkcgo_EVP_MAC_CTX_set_params = dlsym(handle, "EVP_MAC_CTX_set_params\x00", false) + _mkcgo_EVP_MAC_fetch = dlsym(handle, "EVP_MAC_fetch\x00", false) + _mkcgo_EVP_MAC_final = dlsym(handle, "EVP_MAC_final\x00", false) + _mkcgo_EVP_MAC_init = dlsym(handle, "EVP_MAC_init\x00", false) + _mkcgo_EVP_MAC_update = dlsym(handle, "EVP_MAC_update\x00", false) + _mkcgo_EVP_MD_CTX_get_params = dlsym(handle, "EVP_MD_CTX_get_params\x00", false) + _mkcgo_EVP_MD_CTX_gettable_params = dlsym(handle, "EVP_MD_CTX_gettable_params\x00", false) + _mkcgo_EVP_MD_CTX_set_params = dlsym(handle, "EVP_MD_CTX_set_params\x00", false) + _mkcgo_EVP_MD_CTX_settable_params = dlsym(handle, "EVP_MD_CTX_settable_params\x00", false) + _mkcgo_EVP_MD_fetch = dlsym(handle, "EVP_MD_fetch\x00", false) + _mkcgo_EVP_MD_free = dlsym(handle, "EVP_MD_free\x00", false) + _mkcgo_EVP_MD_get0_name = dlsym(handle, "EVP_MD_get0_name\x00", false) + _mkcgo_EVP_MD_get0_provider = dlsym(handle, "EVP_MD_get0_provider\x00", false) + _mkcgo_EVP_MD_get_block_size = dlsym(handle, "EVP_MD_get_block_size\x00", false) + _mkcgo_EVP_MD_get_size = dlsym(handle, "EVP_MD_get_size\x00", false) + _mkcgo_EVP_MD_get_type = dlsym(handle, "EVP_MD_get_type\x00", false) + _mkcgo_EVP_PKEY_CTX_add1_hkdf_info = dlsym(handle, "EVP_PKEY_CTX_add1_hkdf_info\x00", false) + _mkcgo_EVP_PKEY_CTX_new_from_pkey = dlsym(handle, "EVP_PKEY_CTX_new_from_pkey\x00", false) + _mkcgo_EVP_PKEY_CTX_set0_rsa_oaep_label = dlsym(handle, "EVP_PKEY_CTX_set0_rsa_oaep_label\x00", false) + _mkcgo_EVP_PKEY_CTX_set1_hkdf_key = dlsym(handle, "EVP_PKEY_CTX_set1_hkdf_key\x00", false) + _mkcgo_EVP_PKEY_CTX_set1_hkdf_salt = dlsym(handle, "EVP_PKEY_CTX_set1_hkdf_salt\x00", false) + _mkcgo_EVP_PKEY_CTX_set_hkdf_md = dlsym(handle, "EVP_PKEY_CTX_set_hkdf_md\x00", false) + _mkcgo_EVP_PKEY_CTX_set_hkdf_mode = dlsym(handle, "EVP_PKEY_CTX_set_hkdf_mode\x00", false) + _mkcgo_EVP_PKEY_Q_keygen = dlsym(handle, "EVP_PKEY_Q_keygen\x00", false) + _mkcgo_EVP_PKEY_fromdata = dlsym(handle, "EVP_PKEY_fromdata\x00", false) + _mkcgo_EVP_PKEY_fromdata_init = dlsym(handle, "EVP_PKEY_fromdata_init\x00", false) + _mkcgo_EVP_PKEY_get1_encoded_public_key = dlsym(handle, "EVP_PKEY_get1_encoded_public_key\x00", false) + _mkcgo_EVP_PKEY_get_bits = dlsym(handle, "EVP_PKEY_get_bits\x00", false) + _mkcgo_EVP_PKEY_get_bn_param = dlsym(handle, "EVP_PKEY_get_bn_param\x00", false) + _mkcgo_EVP_PKEY_get_size = dlsym(handle, "EVP_PKEY_get_size\x00", false) + _mkcgo_EVP_PKEY_private_check = dlsym(handle, "EVP_PKEY_private_check\x00", false) + _mkcgo_EVP_PKEY_public_check_quick = dlsym(handle, "EVP_PKEY_public_check_quick\x00", false) + _mkcgo_EVP_PKEY_set1_encoded_public_key = dlsym(handle, "EVP_PKEY_set1_encoded_public_key\x00", false) + _mkcgo_EVP_PKEY_up_ref = dlsym(handle, "EVP_PKEY_up_ref\x00", false) + _mkcgo_EVP_SIGNATURE_fetch = dlsym(handle, "EVP_SIGNATURE_fetch\x00", false) + _mkcgo_EVP_SIGNATURE_free = dlsym(handle, "EVP_SIGNATURE_free\x00", false) + _mkcgo_EVP_default_properties_enable_fips = dlsym(handle, "EVP_default_properties_enable_fips\x00", false) + _mkcgo_EVP_default_properties_is_fips_enabled = dlsym(handle, "EVP_default_properties_is_fips_enabled\x00", false) + _mkcgo_OSSL_PARAM_BLD_free = dlsym(handle, "OSSL_PARAM_BLD_free\x00", false) + _mkcgo_OSSL_PARAM_BLD_new = dlsym(handle, "OSSL_PARAM_BLD_new\x00", false) + _mkcgo_OSSL_PARAM_BLD_push_BN = dlsym(handle, "OSSL_PARAM_BLD_push_BN\x00", false) + _mkcgo_OSSL_PARAM_BLD_push_int32 = dlsym(handle, "OSSL_PARAM_BLD_push_int32\x00", false) + _mkcgo_OSSL_PARAM_BLD_push_octet_string = dlsym(handle, "OSSL_PARAM_BLD_push_octet_string\x00", false) + _mkcgo_OSSL_PARAM_BLD_push_utf8_string = dlsym(handle, "OSSL_PARAM_BLD_push_utf8_string\x00", false) + _mkcgo_OSSL_PARAM_BLD_to_param = dlsym(handle, "OSSL_PARAM_BLD_to_param\x00", false) + _mkcgo_OSSL_PARAM_free = dlsym(handle, "OSSL_PARAM_free\x00", false) + _mkcgo_OSSL_PARAM_locate_const = dlsym(handle, "OSSL_PARAM_locate_const\x00", false) + _mkcgo_OSSL_PROVIDER_available = dlsym(handle, "OSSL_PROVIDER_available\x00", false) + _mkcgo_OSSL_PROVIDER_get0_name = dlsym(handle, "OSSL_PROVIDER_get0_name\x00", false) + _mkcgo_OSSL_PROVIDER_try_load = dlsym(handle, "OSSL_PROVIDER_try_load\x00", false) +} + +func MkcgoUnload_3() { + _mkcgo_EC_POINT_set_affine_coordinates = 0 + _mkcgo_ERR_get_error_all = 0 + _mkcgo_EVP_CIPHER_fetch = 0 + _mkcgo_EVP_CIPHER_get0_name = 0 + _mkcgo_EVP_CIPHER_get_block_size = 0 + _mkcgo_EVP_KDF_CTX_free = 0 + _mkcgo_EVP_KDF_CTX_get_kdf_size = 0 + _mkcgo_EVP_KDF_CTX_new = 0 + _mkcgo_EVP_KDF_CTX_set_params = 0 + _mkcgo_EVP_KDF_derive = 0 + _mkcgo_EVP_KDF_fetch = 0 + _mkcgo_EVP_KDF_free = 0 + _mkcgo_EVP_MAC_CTX_dup = 0 + _mkcgo_EVP_MAC_CTX_free = 0 + _mkcgo_EVP_MAC_CTX_new = 0 + _mkcgo_EVP_MAC_CTX_set_params = 0 + _mkcgo_EVP_MAC_fetch = 0 + _mkcgo_EVP_MAC_final = 0 + _mkcgo_EVP_MAC_init = 0 + _mkcgo_EVP_MAC_update = 0 + _mkcgo_EVP_MD_CTX_get_params = 0 + _mkcgo_EVP_MD_CTX_gettable_params = 0 + _mkcgo_EVP_MD_CTX_set_params = 0 + _mkcgo_EVP_MD_CTX_settable_params = 0 + _mkcgo_EVP_MD_fetch = 0 + _mkcgo_EVP_MD_free = 0 + _mkcgo_EVP_MD_get0_name = 0 + _mkcgo_EVP_MD_get0_provider = 0 + _mkcgo_EVP_MD_get_block_size = 0 + _mkcgo_EVP_MD_get_size = 0 + _mkcgo_EVP_MD_get_type = 0 + _mkcgo_EVP_PKEY_CTX_add1_hkdf_info = 0 + _mkcgo_EVP_PKEY_CTX_new_from_pkey = 0 + _mkcgo_EVP_PKEY_CTX_set0_rsa_oaep_label = 0 + _mkcgo_EVP_PKEY_CTX_set1_hkdf_key = 0 + _mkcgo_EVP_PKEY_CTX_set1_hkdf_salt = 0 + _mkcgo_EVP_PKEY_CTX_set_hkdf_md = 0 + _mkcgo_EVP_PKEY_CTX_set_hkdf_mode = 0 + _mkcgo_EVP_PKEY_Q_keygen = 0 + _mkcgo_EVP_PKEY_fromdata = 0 + _mkcgo_EVP_PKEY_fromdata_init = 0 + _mkcgo_EVP_PKEY_get1_encoded_public_key = 0 + _mkcgo_EVP_PKEY_get_bits = 0 + _mkcgo_EVP_PKEY_get_bn_param = 0 + _mkcgo_EVP_PKEY_get_size = 0 + _mkcgo_EVP_PKEY_private_check = 0 + _mkcgo_EVP_PKEY_public_check_quick = 0 + _mkcgo_EVP_PKEY_set1_encoded_public_key = 0 + _mkcgo_EVP_PKEY_up_ref = 0 + _mkcgo_EVP_SIGNATURE_fetch = 0 + _mkcgo_EVP_SIGNATURE_free = 0 + _mkcgo_EVP_default_properties_enable_fips = 0 + _mkcgo_EVP_default_properties_is_fips_enabled = 0 + _mkcgo_OSSL_PARAM_BLD_free = 0 + _mkcgo_OSSL_PARAM_BLD_new = 0 + _mkcgo_OSSL_PARAM_BLD_push_BN = 0 + _mkcgo_OSSL_PARAM_BLD_push_int32 = 0 + _mkcgo_OSSL_PARAM_BLD_push_octet_string = 0 + _mkcgo_OSSL_PARAM_BLD_push_utf8_string = 0 + _mkcgo_OSSL_PARAM_BLD_to_param = 0 + _mkcgo_OSSL_PARAM_free = 0 + _mkcgo_OSSL_PARAM_locate_const = 0 + _mkcgo_OSSL_PROVIDER_available = 0 + _mkcgo_OSSL_PROVIDER_get0_name = 0 + _mkcgo_OSSL_PROVIDER_try_load = 0 +} + +func MkcgoLoad_init_1(handle unsafe.Pointer) { + _mkcgo_FIPS_mode = dlsym(handle, "FIPS_mode\x00", false) + _mkcgo_FIPS_mode_set = dlsym(handle, "FIPS_mode_set\x00", false) +} + +func MkcgoUnload_init_1() { + _mkcgo_FIPS_mode = 0 + _mkcgo_FIPS_mode_set = 0 +} + +func MkcgoLoad_init_3(handle unsafe.Pointer) { + _mkcgo_ERR_clear_error = dlsym(handle, "ERR_clear_error\x00", false) + _mkcgo_EVP_MD_fetch = dlsym(handle, "EVP_MD_fetch\x00", false) + _mkcgo_EVP_MD_free = dlsym(handle, "EVP_MD_free\x00", false) + _mkcgo_EVP_MD_get0_provider = dlsym(handle, "EVP_MD_get0_provider\x00", false) + _mkcgo_EVP_default_properties_is_fips_enabled = dlsym(handle, "EVP_default_properties_is_fips_enabled\x00", false) +} + +func MkcgoUnload_init_3() { + _mkcgo_ERR_clear_error = 0 + _mkcgo_EVP_MD_fetch = 0 + _mkcgo_EVP_MD_free = 0 + _mkcgo_EVP_MD_get0_provider = 0 + _mkcgo_EVP_default_properties_is_fips_enabled = 0 +} + +func MkcgoLoad_legacy_1(handle unsafe.Pointer) { + _mkcgo_DSA_free = dlsym(handle, "DSA_free\x00", false) + _mkcgo_DSA_generate_key = dlsym(handle, "DSA_generate_key\x00", false) + _mkcgo_DSA_get0_key = dlsym(handle, "DSA_get0_key\x00", false) + _mkcgo_DSA_get0_pqg = dlsym(handle, "DSA_get0_pqg\x00", false) + _mkcgo_DSA_new = dlsym(handle, "DSA_new\x00", false) + _mkcgo_DSA_set0_key = dlsym(handle, "DSA_set0_key\x00", false) + _mkcgo_DSA_set0_pqg = dlsym(handle, "DSA_set0_pqg\x00", false) + _mkcgo_EC_KEY_check_key = dlsym(handle, "EC_KEY_check_key\x00", false) + _mkcgo_EC_KEY_free = dlsym(handle, "EC_KEY_free\x00", false) + _mkcgo_EC_KEY_get0_group = dlsym(handle, "EC_KEY_get0_group\x00", false) + _mkcgo_EC_KEY_get0_private_key = dlsym(handle, "EC_KEY_get0_private_key\x00", false) + _mkcgo_EC_KEY_get0_public_key = dlsym(handle, "EC_KEY_get0_public_key\x00", false) + _mkcgo_EC_KEY_new_by_curve_name = dlsym(handle, "EC_KEY_new_by_curve_name\x00", false) + _mkcgo_EC_KEY_set_private_key = dlsym(handle, "EC_KEY_set_private_key\x00", false) + _mkcgo_EC_KEY_set_public_key = dlsym(handle, "EC_KEY_set_public_key\x00", false) + _mkcgo_EC_KEY_set_public_key_affine_coordinates = dlsym(handle, "EC_KEY_set_public_key_affine_coordinates\x00", false) + _mkcgo_EC_POINT_get_affine_coordinates_GFp = dlsym(handle, "EC_POINT_get_affine_coordinates_GFp\x00", false) + _mkcgo_ERR_get_error_line = dlsym(handle, "ERR_get_error_line\x00", false) + _mkcgo_EVP_CIPHER_get_block_size = dlsym(handle, "EVP_CIPHER_block_size\x00", false) + _mkcgo_EVP_MD_get_block_size = dlsym(handle, "EVP_MD_block_size\x00", false) + _mkcgo_EVP_MD_get_size = dlsym(handle, "EVP_MD_size\x00", false) + _mkcgo_EVP_PKEY_assign = dlsym(handle, "EVP_PKEY_assign\x00", false) + _mkcgo_EVP_PKEY_get0_DSA = dlsym(handle, "EVP_PKEY_get0_DSA\x00", false) + _mkcgo_EVP_PKEY_get0_EC_KEY = dlsym(handle, "EVP_PKEY_get0_EC_KEY\x00", false) + _mkcgo_EVP_PKEY_get1_RSA = dlsym(handle, "EVP_PKEY_get1_RSA\x00", false) + _mkcgo_EVP_PKEY_get_bits = dlsym(handle, "EVP_PKEY_bits\x00", false) + _mkcgo_EVP_PKEY_get_size = dlsym(handle, "EVP_PKEY_size\x00", false) + _mkcgo_EVP_PKEY_set1_EC_KEY = dlsym(handle, "EVP_PKEY_set1_EC_KEY\x00", false) + _mkcgo_FIPS_mode = dlsym(handle, "FIPS_mode\x00", false) + _mkcgo_FIPS_mode_set = dlsym(handle, "FIPS_mode_set\x00", false) + _mkcgo_HMAC_CTX_copy = dlsym(handle, "HMAC_CTX_copy\x00", false) + _mkcgo_HMAC_CTX_free = dlsym(handle, "HMAC_CTX_free\x00", false) + _mkcgo_HMAC_CTX_new = dlsym(handle, "HMAC_CTX_new\x00", false) + _mkcgo_HMAC_Final = dlsym(handle, "HMAC_Final\x00", false) + _mkcgo_HMAC_Init_ex = dlsym(handle, "HMAC_Init_ex\x00", false) + _mkcgo_HMAC_Update = dlsym(handle, "HMAC_Update\x00", false) + _mkcgo_RSA_free = dlsym(handle, "RSA_free\x00", false) + _mkcgo_RSA_get0_crt_params = dlsym(handle, "RSA_get0_crt_params\x00", false) + _mkcgo_RSA_get0_factors = dlsym(handle, "RSA_get0_factors\x00", false) + _mkcgo_RSA_get0_key = dlsym(handle, "RSA_get0_key\x00", false) + _mkcgo_RSA_new = dlsym(handle, "RSA_new\x00", false) + _mkcgo_RSA_set0_crt_params = dlsym(handle, "RSA_set0_crt_params\x00", false) + _mkcgo_RSA_set0_factors = dlsym(handle, "RSA_set0_factors\x00", false) + _mkcgo_RSA_set0_key = dlsym(handle, "RSA_set0_key\x00", false) +} + +func MkcgoUnload_legacy_1() { + _mkcgo_DSA_free = 0 + _mkcgo_DSA_generate_key = 0 + _mkcgo_DSA_get0_key = 0 + _mkcgo_DSA_get0_pqg = 0 + _mkcgo_DSA_new = 0 + _mkcgo_DSA_set0_key = 0 + _mkcgo_DSA_set0_pqg = 0 + _mkcgo_EC_KEY_check_key = 0 + _mkcgo_EC_KEY_free = 0 + _mkcgo_EC_KEY_get0_group = 0 + _mkcgo_EC_KEY_get0_private_key = 0 + _mkcgo_EC_KEY_get0_public_key = 0 + _mkcgo_EC_KEY_new_by_curve_name = 0 + _mkcgo_EC_KEY_set_private_key = 0 + _mkcgo_EC_KEY_set_public_key = 0 + _mkcgo_EC_KEY_set_public_key_affine_coordinates = 0 + _mkcgo_EC_POINT_get_affine_coordinates_GFp = 0 + _mkcgo_ERR_get_error_line = 0 + _mkcgo_EVP_CIPHER_get_block_size = 0 + _mkcgo_EVP_MD_get_block_size = 0 + _mkcgo_EVP_MD_get_size = 0 + _mkcgo_EVP_PKEY_assign = 0 + _mkcgo_EVP_PKEY_get0_DSA = 0 + _mkcgo_EVP_PKEY_get0_EC_KEY = 0 + _mkcgo_EVP_PKEY_get1_RSA = 0 + _mkcgo_EVP_PKEY_get_bits = 0 + _mkcgo_EVP_PKEY_get_size = 0 + _mkcgo_EVP_PKEY_set1_EC_KEY = 0 + _mkcgo_FIPS_mode = 0 + _mkcgo_FIPS_mode_set = 0 + _mkcgo_HMAC_CTX_copy = 0 + _mkcgo_HMAC_CTX_free = 0 + _mkcgo_HMAC_CTX_new = 0 + _mkcgo_HMAC_Final = 0 + _mkcgo_HMAC_Init_ex = 0 + _mkcgo_HMAC_Update = 0 + _mkcgo_RSA_free = 0 + _mkcgo_RSA_get0_crt_params = 0 + _mkcgo_RSA_get0_factors = 0 + _mkcgo_RSA_get0_key = 0 + _mkcgo_RSA_new = 0 + _mkcgo_RSA_set0_crt_params = 0 + _mkcgo_RSA_set0_factors = 0 + _mkcgo_RSA_set0_key = 0 +} + +func MkcgoLoad_version(handle unsafe.Pointer) { + _mkcgo_OPENSSL_version_major = dlsym(handle, "OPENSSL_version_major\x00", true) + _mkcgo_OPENSSL_version_minor = dlsym(handle, "OPENSSL_version_minor\x00", true) + _mkcgo_OPENSSL_version_patch = dlsym(handle, "OPENSSL_version_patch\x00", true) + _mkcgo_OpenSSL_version_num = dlsym(handle, "OpenSSL_version_num\x00", true) +} + +func MkcgoUnload_version() { + _mkcgo_OPENSSL_version_major = 0 + _mkcgo_OPENSSL_version_minor = 0 + _mkcgo_OPENSSL_version_patch = 0 + _mkcgo_OpenSSL_version_num = 0 +} diff --git a/openssl.go b/openssl.go index f3377d72..f8b8b3dc 100644 --- a/openssl.go +++ b/openssl.go @@ -3,24 +3,6 @@ // Package openssl provides access to OpenSSL cryptographic functions. package openssl -/* -#include // for free() - -static inline void -go_openssl_do_leak_check(void) -{ -#ifndef __has_feature -#define __has_feature(x) 0 -#endif - -#if (defined(__SANITIZE_ADDRESS__) && __SANITIZE_ADDRESS__) || \ - __has_feature(address_sanitizer) - extern void __lsan_do_leak_check(void); - __lsan_do_leak_check(); -#endif -} -*/ -import "C" import ( "errors" "math/bits" @@ -103,11 +85,6 @@ type fail string func (e fail) Error() string { return "openssl: " + string(e) + " failed" } -// VersionText returns the version text of the OpenSSL currently loaded. -func VersionText() string { - return C.GoString((*C.char)(unsafe.Pointer(ossl.OpenSSL_version(0)))) -} - // FIPS returns true if OpenSSL is running in FIPS mode and there is // a provider available that supports FIPS. It returns false otherwise. // All OpenSSL functions used in here should be tagged with "init_1" or "init_3" in shims.h. @@ -166,17 +143,6 @@ func FIPSCapable() bool { return false } -// isProviderAvailable checks if the provider with the given name is available. -// This function is used in export_test.go, but must be defined here as test files can't access C functions. -func isProviderAvailable(name string) bool { - if vMajor == 1 { - return false - } - providerName := C.CString(name) - defer C.free(unsafe.Pointer(providerName)) - return ossl.OSSL_PROVIDER_available(nil, (*byte)(unsafe.Pointer(providerName))) == 1 -} - // SetFIPS enables or disables FIPS mode. // // For OpenSSL 3, if there is no provider available that supports FIPS mode, @@ -289,7 +255,7 @@ func cryptoMalloc(n int) unsafe.Pointer { if p == nil { // Un-recover()-ably crash the program in the same manner as the // C.malloc() wrapper function. - runtime_throw("openssl: CRYPTO_malloc failed") + panic("openssl: CRYPTO_malloc failed") } return p } @@ -366,10 +332,6 @@ func bnToBinPad(bn ossl.BIGNUM_PTR, to []byte) error { return err } -func CheckLeaks() { - C.go_openssl_do_leak_check() -} - // versionAtOrAbove returns true when // (vMajor, vMinor, vPatch) >= (major, minor, patch), // compared lexicographically. @@ -382,3 +344,18 @@ func bigEndianUint64(b []byte) uint64 { return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 } + +// VersionText returns the version text of the OpenSSL currently loaded. +func VersionText() string { + // For nocgo, we need to convert the C string manually + return goString(ossl.OpenSSL_version(0)) +} + +// isProviderAvailable reports whether a provider with the given name is available. +// This function is used in export_test.go, but must be defined here as test files can't access C functions. +func isProviderAvailable(name string) bool { + if vMajor == 1 { + return false + } + return ossl.OSSL_PROVIDER_available(nil, unsafe.StringData(name+"\x00")) == 1 +} diff --git a/openssl_cgo.go b/openssl_cgo.go new file mode 100644 index 00000000..f3a25d74 --- /dev/null +++ b/openssl_cgo.go @@ -0,0 +1,39 @@ +//go:build cgo + +package openssl + +/* +#include // for free() + +static inline void +go_openssl_do_leak_check(void) +{ +#ifndef __has_feature +#define __has_feature(x) 0 +#endif + +#if (defined(__SANITIZE_ADDRESS__) && __SANITIZE_ADDRESS__) || \ + __has_feature(address_sanitizer) + extern void __lsan_do_leak_check(void); + __lsan_do_leak_check(); +#endif +} +*/ +import "C" +import ( + "unsafe" +) + +// goString converts a C string pointer to a Go string for cgo mode +func goString(ptr *byte) string { + return C.GoString((*C.char)(unsafe.Pointer(ptr))) +} + +// goBytes converts a C byte array to a Go byte slice for cgo mode +func goBytes(ptr unsafe.Pointer, length int) []byte { + return C.GoBytes(ptr, C.int(length)) +} + +func CheckLeaks() { + C.go_openssl_do_leak_check() +} diff --git a/openssl_nocgo.go b/openssl_nocgo.go new file mode 100644 index 00000000..f801981d --- /dev/null +++ b/openssl_nocgo.go @@ -0,0 +1,38 @@ +//go:build !cgo + +package openssl + +import ( + "unsafe" +) + +// goString converts a C string pointer to a Go string for nocgo mode +func goString(ptr *byte) string { + if ptr == nil { + return "" + } + var result []byte + for i := 0; ; i++ { + b := *(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(ptr)) + uintptr(i))) + if b == 0 { + break + } + result = append(result, b) + } + return string(result) +} + +// goBytes converts a C byte array to a Go byte slice for nocgo mode +func goBytes(ptr unsafe.Pointer, length int) []byte { + if ptr == nil || length == 0 { + return nil + } + // Copy the data to Go memory, similar to C.GoBytes + result := make([]byte, length) + copy(result, unsafe.Slice((*byte)(ptr), length)) + return result +} + +func CheckLeaks() { + // No-op for nocgo mode - leak checking requires CGO +} diff --git a/params.go b/params.go index a5b6cdb9..3bdc8037 100644 --- a/params.go +++ b/params.go @@ -2,7 +2,6 @@ package openssl -import "C" import ( "runtime" diff --git a/pbkdf2.go b/pbkdf2.go index ace373e6..caaf3832 100644 --- a/pbkdf2.go +++ b/pbkdf2.go @@ -2,7 +2,6 @@ package openssl -import "C" import ( "errors" "hash" diff --git a/provideropenssl.go b/provideropenssl.go index 1d8f3ad0..b29b05bf 100644 --- a/provideropenssl.go +++ b/provideropenssl.go @@ -1,4 +1,4 @@ -//go:build !cmd_go_bootstrap && cgo +//go:build !cmd_go_bootstrap package openssl diff --git a/providersymcrypt.go b/providersymcrypt.go index 693849f1..aa4c445b 100644 --- a/providersymcrypt.go +++ b/providersymcrypt.go @@ -1,4 +1,4 @@ -//go:build !cmd_go_bootstrap && cgo +//go:build !cmd_go_bootstrap package openssl diff --git a/rand.go b/rand.go index 34f376be..bcc58f2e 100644 --- a/rand.go +++ b/rand.go @@ -2,7 +2,6 @@ package openssl -import "C" import "github.com/golang-fips/openssl/v2/internal/ossl" type randReader int diff --git a/rc4.go b/rc4.go index b585668e..25fa08d0 100644 --- a/rc4.go +++ b/rc4.go @@ -2,7 +2,6 @@ package openssl -import "C" import ( "runtime" diff --git a/rsa.go b/rsa.go index 7c1a3f06..343f3cfb 100644 --- a/rsa.go +++ b/rsa.go @@ -2,7 +2,6 @@ package openssl -import "C" import ( "crypto" "crypto/subtle" diff --git a/tls1prf.go b/tls1prf.go index 55fc0332..4c33fadd 100644 --- a/tls1prf.go +++ b/tls1prf.go @@ -2,7 +2,6 @@ package openssl -import "C" import ( "crypto" "errors" diff --git a/zaes.go b/zaes.go index e60a5dde..4d945290 100644 --- a/zaes.go +++ b/zaes.go @@ -1,6 +1,6 @@ // Code generated by cmd/genaesmodes. DO NOT EDIT. -//go:build cgo && !cmd_go_bootstrap +//go:build !cmd_go_bootstrap package openssl