From 6ccf9699ad08986fcd700e0e40d5df0806334390 Mon Sep 17 00:00:00 2001 From: Quim Muntal Date: Mon, 22 Jan 2024 12:10:50 +0000 Subject: [PATCH] port necessary dsa functions to openssl 3 --- dsa.go | 42 ++++++++++++++++++++++++++++++++++-------- dsa_test.go | 12 +++++++++--- openssl_test.go | 2 +- shims.h | 1 + 4 files changed, 45 insertions(+), 12 deletions(-) diff --git a/dsa.go b/dsa.go index dec855ee..51905914 100644 --- a/dsa.go +++ b/dsa.go @@ -249,34 +249,60 @@ func newDSA3(params DSAParameters, X, Y BigInt) (C.GO_EVP_PKEY_PTR, error) { return nil, newOpenSSLError("OSSL_PARAM_BLD_new") } defer C.go_openssl_OSSL_PARAM_BLD_free(bld) - selection := C.int(C.GO_EVP_PKEY_PUBLIC_KEY) - pub := bigToBN(Y) - defer C.go_openssl_BN_free(pub) - if C.go_openssl_OSSL_PARAM_BLD_push_BN(bld, paramPubKey, pub) != 1 { + p, q, g := bigToBN(params.P), bigToBN(params.Q), bigToBN(params.G) + defer func() { + C.go_openssl_BN_free(p) + C.go_openssl_BN_free(q) + C.go_openssl_BN_free(g) + }() + if C.go_openssl_OSSL_PARAM_BLD_push_BN(bld, paramP, p) != 1 || + C.go_openssl_OSSL_PARAM_BLD_push_BN(bld, paramQ, q) != 1 || + C.go_openssl_OSSL_PARAM_BLD_push_BN(bld, paramG, g) != 1 { return nil, newOpenSSLError("OSSL_PARAM_BLD_push_BN") } + selection := C.int(C.GO_EVP_PKEY_KEYPAIR) + if Y != nil { + pub := bigToBN(Y) + defer C.go_openssl_BN_free(pub) + if C.go_openssl_OSSL_PARAM_BLD_push_BN(bld, paramPubKey, pub) != 1 { + return nil, newOpenSSLError("OSSL_PARAM_BLD_push_BN") + } + selection = C.int(C.GO_EVP_PKEY_PUBLIC_KEY) + } if X != nil { priv := bigToBN(X) defer C.go_openssl_BN_clear_free(priv) if C.go_openssl_OSSL_PARAM_BLD_push_BN(bld, paramPrivKey, priv) != 1 { return nil, newOpenSSLError("OSSL_PARAM_BLD_push_BN") } - selection = C.GO_EVP_PKEY_KEYPAIR } bldparams := C.go_openssl_OSSL_PARAM_BLD_to_param(bld) if bldparams == nil { return nil, newOpenSSLError("OSSL_PARAM_BLD_to_param") } defer C.go_openssl_OSSL_PARAM_free(bldparams) - pkey, err := newEvpFromParams(C.GO_EVP_PKEY_EC, selection, bldparams) + pkey, err := newEvpFromParams(C.GO_EVP_PKEY_DSA, selection, bldparams) if err != nil { return nil, err } if Y != nil { return pkey, nil } - // Generate the key. - return nil, nil + // pkey doesn't contain the public/private components. We use it + // as domain parameters placeholder to generate the final key. + defer C.go_openssl_EVP_PKEY_free(pkey) + ctx := C.go_openssl_EVP_PKEY_CTX_new_from_pkey(nil, pkey, nil) + if ctx == nil { + return nil, newOpenSSLError("EVP_PKEY_CTX_new_from_pkey") + } + if C.go_openssl_EVP_PKEY_keygen_init(ctx) != 1 { + return nil, newOpenSSLError("EVP_PKEY_keygen_init") + } + var gkey C.GO_EVP_PKEY_PTR + if C.go_openssl_EVP_PKEY_keygen(ctx, &gkey) != 1 { + return nil, newOpenSSLError("EVP_PKEY_keygen") + } + return gkey, nil } // getDSA returns the DSA from pkey. diff --git a/dsa_test.go b/dsa_test.go index 7f1fee2a..249791a3 100644 --- a/dsa_test.go +++ b/dsa_test.go @@ -146,9 +146,15 @@ func TestDSANewPrivateKeyWithDegenerateKeys(t *testing.T) { Q: bbig.Enc(fromHex(test.q)), G: bbig.Enc(fromHex(test.g)), } - _, err := openssl.NewPrivateKeyDSA(params, bbig.Enc(fromHex(test.x)), bbig.Enc(fromHex(test.y))) - if err == nil { - t.Errorf("#%d: error generating key: %s", i, err) + x, y := bbig.Enc(fromHex(test.x)), bbig.Enc(fromHex(test.y)) + priv, err := openssl.NewPrivateKeyDSA(params, x, y) + if err != nil { + // Some OpenSSL 1 fails to create degenerated private keys, which is fine. + continue + } + hashed := []byte("testing") + if _, err := openssl.SignDSA(priv, hashed); err == nil { + t.Errorf("#%d: unexpected success", i) } } } diff --git a/openssl_test.go b/openssl_test.go index cbae1615..267a92ba 100644 --- a/openssl_test.go +++ b/openssl_test.go @@ -46,7 +46,7 @@ func getVersion() string { } func TestMain(m *testing.M) { - v := getVersion() + v := "libcrypto.so.3.0.1" //getVersion() fmt.Printf("Using %s\n", v) err := openssl.Init(v) if err != nil { diff --git a/shims.h b/shims.h index fb16e91a..4c9a492b 100644 --- a/shims.h +++ b/shims.h @@ -285,6 +285,7 @@ DEFINEFUNC_LEGACY_1(int, EVP_PKEY_assign, (GO_EVP_PKEY_PTR pkey, int type, void DEFINEFUNC(int, EVP_PKEY_verify, (GO_EVP_PKEY_CTX_PTR ctx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbslen), (ctx, sig, siglen, tbs, tbslen)) \ DEFINEFUNC(GO_EVP_PKEY_CTX_PTR, EVP_PKEY_CTX_new, (GO_EVP_PKEY_PTR arg0, GO_ENGINE_PTR arg1), (arg0, arg1)) \ DEFINEFUNC(GO_EVP_PKEY_CTX_PTR, EVP_PKEY_CTX_new_id, (int id, GO_ENGINE_PTR e), (id, e)) \ +DEFINEFUNC_3_0(GO_EVP_PKEY_CTX_PTR, EVP_PKEY_CTX_new_from_pkey, (GO_OSSL_LIB_CTX_PTR libctx, GO_EVP_PKEY_PTR pkey, const char *propquery), (libctx, pkey, propquery)) \ 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)) \