Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate PKEYs using EVP_PKEY_Q_keygen #229

Merged
merged 6 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions cmd/checkheader/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,11 @@ func tryConvertDefineFunc(w io.Writer, l string, i int) bool {
if !strings.HasPrefix(l, "DEFINEFUNC") {
return false
}
if strings.HasPrefix(l, "DEFINEFUNC_VARIADIC") {
// Variadic functions are not supported. There is not enough
// information in the macro to create use it in writeDefineFunc.
return false
}
i1 := strings.IndexByte(l, '(')
// The first ")," match is always the end of the argument list parameter.
// We are not interested in the last parameter and parsing them would complicate the algorithm.
Expand Down
5 changes: 1 addition & 4 deletions ed25519.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"runtime"
"strconv"
"sync"
"unsafe"
)

const (
Expand Down Expand Up @@ -37,9 +36,7 @@ var supportsEd25519 = sync.OnceValue(func() bool {
}
}
case 3:
name := C.CString("ED25519")
defer C.free(unsafe.Pointer(name))
sig := C.go_openssl_EVP_SIGNATURE_fetch(nil, name, nil)
sig := C.go_openssl_EVP_SIGNATURE_fetch(nil, keyTypeED25519, nil)
if sig != nil {
C.go_openssl_EVP_SIGNATURE_free(sig)
return true
Expand Down
66 changes: 46 additions & 20 deletions evp.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ import (
"unsafe"
)

var (
keyTypeRSA = C.CString("RSA")
keyTypeEC = C.CString("EC")
keyTypeED25519 = C.CString("ED25519")
)

// cacheMD is a cache of crypto.Hash to GO_EVP_MD_PTR.
var cacheMD sync.Map

Expand Down Expand Up @@ -157,33 +163,53 @@ func cryptoHashToMD(ch crypto.Hash) (md C.GO_EVP_MD_PTR) {
return nil
}

// generateEVPPKey generates a new EVP_PKEY with the given id and properties.
func generateEVPPKey(id C.int, bits int, curve string) (C.GO_EVP_PKEY_PTR, error) {
if bits != 0 && curve != "" {
return nil, fail("incorrect generateEVPPKey parameters")
}
ctx := C.go_openssl_EVP_PKEY_CTX_new_id(id, nil)
if ctx == nil {
return nil, newOpenSSLError("EVP_PKEY_CTX_new_id failed")
}
defer C.go_openssl_EVP_PKEY_CTX_free(ctx)
if C.go_openssl_EVP_PKEY_keygen_init(ctx) != 1 {
return nil, newOpenSSLError("EVP_PKEY_keygen_init failed")
}
if bits != 0 {
if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, id, -1, C.GO_EVP_PKEY_CTRL_RSA_KEYGEN_BITS, C.int(bits), nil) != 1 {
return nil, newOpenSSLError("EVP_PKEY_CTX_ctrl failed")
var pkey C.GO_EVP_PKEY_PTR
switch vMajor {
case 1:
ctx := C.go_openssl_EVP_PKEY_CTX_new_id(id, nil)
if ctx == nil {
return nil, newOpenSSLError("EVP_PKEY_CTX_new_id")
}
defer C.go_openssl_EVP_PKEY_CTX_free(ctx)
if C.go_openssl_EVP_PKEY_keygen_init(ctx) != 1 {
return nil, newOpenSSLError("EVP_PKEY_keygen_init")
}
if bits != 0 {
if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, id, -1, C.GO_EVP_PKEY_CTRL_RSA_KEYGEN_BITS, C.int(bits), nil) != 1 {
return nil, newOpenSSLError("EVP_PKEY_CTX_ctrl")
}
}
}
if curve != "" {
nid := curveNID(curve)
if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, id, -1, C.GO_EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, nid, nil) != 1 {
return nil, newOpenSSLError("EVP_PKEY_CTX_ctrl failed")
if curve != "" {
if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, id, -1, C.GO_EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, curveNID(curve), nil) != 1 {
return nil, newOpenSSLError("EVP_PKEY_CTX_ctrl")
}
}
if C.go_openssl_EVP_PKEY_keygen(ctx, &pkey) != 1 {
return nil, newOpenSSLError("EVP_PKEY_keygen")
}
case 3:
switch id {
case C.GO_EVP_PKEY_RSA:
pkey = C.go_openssl_EVP_PKEY_Q_keygen_RSA(nil, nil, keyTypeRSA, C.size_t(bits))
case C.GO_EVP_PKEY_EC:
pkey = C.go_openssl_EVP_PKEY_Q_keygen_EC(nil, nil, keyTypeEC, C.go_openssl_OBJ_nid2sn(curveNID(curve)))
case C.GO_EVP_PKEY_ED25519:
pkey = C.go_openssl_EVP_PKEY_Q_keygen(nil, nil, keyTypeED25519)
default:
panic("unsupported key type '" + strconv.Itoa(int(id)) + "'")
}
if pkey == nil {
return nil, newOpenSSLError("EVP_PKEY_Q_keygen")
}
default:
panic(errUnsupportedVersion())
}
var pkey C.GO_EVP_PKEY_PTR
if C.go_openssl_EVP_PKEY_keygen(ctx, &pkey) != 1 {
return nil, newOpenSSLError("EVP_PKEY_keygen failed")
}

return pkey, nil
}

Expand Down
8 changes: 8 additions & 0 deletions goopenssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#define DEFINEFUNC_3_0(ret, func, args, argscall) DEFINEFUNC(ret, func, args, argscall)
#define DEFINEFUNC_RENAMED_1_1(ret, func, oldfunc, args, argscall) DEFINEFUNC(ret, func, args, argscall)
#define DEFINEFUNC_RENAMED_3_0(ret, func, oldfunc, args, argscall) DEFINEFUNC(ret, func, args, argscall)
#define DEFINEFUNC_VARIADIC_3_0(ret, func, newname, args, argscall) DEFINEFUNC(ret, newname, args, argscall)

FOR_ALL_OPENSSL_FUNCTIONS

Expand All @@ -34,6 +35,7 @@ FOR_ALL_OPENSSL_FUNCTIONS
#undef DEFINEFUNC_3_0
#undef DEFINEFUNC_RENAMED_1_1
#undef DEFINEFUNC_RENAMED_3_0
#undef DEFINEFUNC_VARIADIC_3_0

// go_openssl_fips_enabled returns 1 if FIPS mode is enabled, 0 otherwise.
// As a special case, it returns -1 if it cannot determine if FIPS mode is enabled.
Expand Down Expand Up @@ -140,6 +142,11 @@ go_openssl_load_functions(void* handle, unsigned int major, unsigned int minor,
{ \
DEFINEFUNC_INTERNAL(func, #func) \
}
#define DEFINEFUNC_VARIADIC_3_0(ret, func, newname, args, argscall) \
if (major == 3) \
{ \
DEFINEFUNC_INTERNAL(newname, #func) \
}

FOR_ALL_OPENSSL_FUNCTIONS

Expand All @@ -152,6 +159,7 @@ FOR_ALL_OPENSSL_FUNCTIONS
#undef DEFINEFUNC_3_0
#undef DEFINEFUNC_RENAMED_1_1
#undef DEFINEFUNC_RENAMED_3_0
#undef DEFINEFUNC_VARIADIC_3_0
}

static unsigned long
Expand Down
3 changes: 3 additions & 0 deletions goopenssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ int go_openssl_DSA_set0_key_backport(GO_DSA_PTR d, GO_BIGNUM_PTR pub_key, GO_BIG
DEFINEFUNC(ret, func, args, argscall)
#define DEFINEFUNC_RENAMED_3_0(ret, func, oldfunc, args, argscall) \
DEFINEFUNC(ret, func, args, argscall)
#define DEFINEFUNC_VARIADIC_3_0(ret, func, newname, args, argscall) \
DEFINEFUNC(ret, newname, args, argscall)

FOR_ALL_OPENSSL_FUNCTIONS

Expand All @@ -71,6 +73,7 @@ FOR_ALL_OPENSSL_FUNCTIONS
#undef DEFINEFUNC_3_0
#undef DEFINEFUNC_RENAMED_1_1
#undef DEFINEFUNC_RENAMED_3_0
#undef DEFINEFUNC_VARIADIC_3_0

// go_hash_sum copies ctx into ctx2 and calls EVP_DigestFinal using ctx2.
// This is necessary because Go hash.Hash mandates that Sum has no effect
Expand Down
12 changes: 12 additions & 0 deletions shims.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,15 @@ typedef void* GO_SHA_CTX_PTR;
// DEFINEFUNC_RENAMED_3_0 acts like DEFINEFUNC but tries to load the function using the new name when using >= 3.x
// and the old name when using 1.x. In both cases the function will have the new name.
//
// DEFINEFUNC_VARIADIC_3_0 acts like DEFINEFUNC but creates an alias with a more specific signature.
// This is necessary to call variadic functions (functions that accept a variable number of arguments)
// because variadic functions are not directly compatible with cgo. By defining a cgo-compatible alias
// for each desired signature, the C compiler handles the variadic arguments rather than cgo.
// Variadic functions are the only known incompatibility of this kind.
// If you use this macro for a different reason, consider renaming it to something more general first.
// See https://github.com/golang/go/issues/975.
// The process is aborted if the function can't be loaded when using 3.0.0 or higher.
//
// #include <openssl/crypto.h>
// #include <openssl/err.h>
// #include <openssl/rsa.h>
Expand Down Expand Up @@ -298,6 +307,9 @@ DEFINEFUNC(int, EVP_PKEY_paramgen_init, (GO_EVP_PKEY_CTX_PTR ctx), (ctx)) \
DEFINEFUNC(int, EVP_PKEY_paramgen, (GO_EVP_PKEY_CTX_PTR ctx, GO_EVP_PKEY_PTR *ppkey), (ctx, ppkey)) \
DEFINEFUNC(int, EVP_PKEY_keygen_init, (GO_EVP_PKEY_CTX_PTR ctx), (ctx)) \
DEFINEFUNC(int, EVP_PKEY_keygen, (GO_EVP_PKEY_CTX_PTR ctx, GO_EVP_PKEY_PTR *ppkey), (ctx, ppkey)) \
DEFINEFUNC_VARIADIC_3_0(GO_EVP_PKEY_PTR, EVP_PKEY_Q_keygen, EVP_PKEY_Q_keygen, (GO_OSSL_LIB_CTX_PTR ctx, const char *propq, const char *type), (ctx, propq, type)) \
DEFINEFUNC_VARIADIC_3_0(GO_EVP_PKEY_PTR, EVP_PKEY_Q_keygen, EVP_PKEY_Q_keygen_RSA, (GO_OSSL_LIB_CTX_PTR ctx, const char *propq, const char *type, size_t arg1), (ctx, propq, type, arg1)) \
DEFINEFUNC_VARIADIC_3_0(GO_EVP_PKEY_PTR, EVP_PKEY_Q_keygen, EVP_PKEY_Q_keygen_EC, (GO_OSSL_LIB_CTX_PTR ctx, const char *propq, const char *type, const char *arg1), (ctx, propq, type, arg1)) \
DEFINEFUNC(void, EVP_PKEY_CTX_free, (GO_EVP_PKEY_CTX_PTR arg0), (arg0)) \
DEFINEFUNC(int, EVP_PKEY_CTX_ctrl, (GO_EVP_PKEY_CTX_PTR ctx, int keytype, int optype, int cmd, int p1, void *p2), (ctx, keytype, optype, cmd, p1, p2)) \
DEFINEFUNC(int, EVP_PKEY_decrypt, (GO_EVP_PKEY_CTX_PTR arg0, unsigned char *arg1, size_t *arg2, const unsigned char *arg3, size_t arg4), (arg0, arg1, arg2, arg3, arg4)) \
Expand Down
Loading