diff --git a/dsa.go b/dsa.go index 73dcc3e8..dec855ee 100644 --- a/dsa.go +++ b/dsa.go @@ -81,7 +81,11 @@ func GenerateDSAParameters(L, N int) (DSAParameters, error) { switch vMajor { case 1: dsa := getDSA(pkey) - C.go_openssl_DSA_get0_pqg(dsa, &p, &q, &g) + if vMinor == 0 { + C.go_openssl_DSA_get0_pqg_backport(dsa, &p, &q, &g) + } else { + C.go_openssl_DSA_get0_pqg(dsa, &p, &q, &g) + } case 3: defer func() { C.go_openssl_BN_free(p) @@ -142,7 +146,11 @@ func GenerateKeyDSA(params DSAParameters) (*PrivateKeyDSA, error) { switch vMajor { case 1: dsa := getDSA(pkey) - C.go_openssl_DSA_get0_key(dsa, &y, &x) + if vMinor == 0 { + C.go_openssl_DSA_get0_key_backport(dsa, &y, &x) + } else { + C.go_openssl_DSA_get0_key(dsa, &y, &x) + } case 3: defer func() { C.go_openssl_BN_clear_free(x) @@ -187,7 +195,13 @@ func newDSA1(params DSAParameters, X, Y BigInt) (C.GO_EVP_PKEY_PTR, error) { } dsa := C.go_openssl_DSA_new() p, q, g := bigToBN(params.P), bigToBN(params.Q), bigToBN(params.G) - if C.go_openssl_DSA_set0_pqg(dsa, p, q, g) != 1 { + var ret C.int + if vMinor == 0 { + ret = C.go_openssl_DSA_set0_pqg_backport(dsa, p, q, g) + } else { + ret = C.go_openssl_DSA_set0_pqg(dsa, p, q, g) + } + if ret != 1 { C.go_openssl_BN_free(p) C.go_openssl_BN_free(q) C.go_openssl_BN_free(g) @@ -196,7 +210,12 @@ func newDSA1(params DSAParameters, X, Y BigInt) (C.GO_EVP_PKEY_PTR, error) { } if Y != nil { pub, priv := bigToBN(Y), bigToBN(X) - if C.go_openssl_DSA_set0_key(dsa, pub, priv) != 1 { + if vMinor == 0 { + ret = C.go_openssl_DSA_set0_key_backport(dsa, pub, priv) + } else { + ret = C.go_openssl_DSA_set0_key(dsa, pub, priv) + } + if ret != 1 { C.go_openssl_BN_free(pub) C.go_openssl_BN_clear_free(priv) C.go_openssl_DSA_free(dsa) diff --git a/goopenssl.h b/goopenssl.h index e488bf20..a50caa3d 100644 --- a/goopenssl.h +++ b/goopenssl.h @@ -28,6 +28,10 @@ int go_openssl_version_patch(void* handle); int go_openssl_thread_setup(void); void go_openssl_load_functions(void* handle, unsigned int major, unsigned int minor, unsigned int patch); const GO_EVP_MD_PTR go_openssl_EVP_md5_sha1_backport(void); +void go_openssl_DSA_get0_pqg_backport(const GO_DSA_PTR d, GO_BIGNUM_PTR *p, GO_BIGNUM_PTR *q, GO_BIGNUM_PTR *g); +int go_openssl_DSA_set0_pqg_backport(GO_DSA_PTR d, GO_BIGNUM_PTR p, GO_BIGNUM_PTR q, GO_BIGNUM_PTR g); +void go_openssl_DSA_get0_key_backport(const GO_DSA_PTR d, GO_BIGNUM_PTR *pub_key, GO_BIGNUM_PTR *priv_key); +int go_openssl_DSA_set0_key_backport(GO_DSA_PTR d, GO_BIGNUM_PTR pub_key, GO_BIGNUM_PTR priv_key); // Define pointers to all the used OpenSSL functions. // Calling C function pointers from Go is currently not supported. diff --git a/port_dsa.c b/port_dsa.c new file mode 100644 index 00000000..e96c8500 --- /dev/null +++ b/port_dsa.c @@ -0,0 +1,83 @@ +// The following is a partial backport of crypto/dsa/dsa_pmeth.c, +// commit cbc8a839959418d8a2c2e3ec6bdf394852c9501e on the +// OpenSSL_1_1_0-stable branch. The ctrl function has been removed. + +#include "goopenssl.h" + +struct dsa_st +{ + int _ignored0; + long _ignored1; + int _ignored2; + GO_BIGNUM_PTR p; + GO_BIGNUM_PTR q; + GO_BIGNUM_PTR g; + GO_BIGNUM_PTR pub_key; + GO_BIGNUM_PTR priv_key; +}; + + +void go_openssl_DSA_get0_pqg_backport(const GO_DSA_PTR dsa, + GO_BIGNUM_PTR *p, GO_BIGNUM_PTR *q, GO_BIGNUM_PTR *g) +{ + const struct dsa_st *d = dsa; + if (p != NULL) + *p = d->p; + if (q != NULL) + *q = d->q; + if (g != NULL) + *g = d->g; +} + +int go_openssl_DSA_set0_pqg_backport(GO_DSA_PTR dsa, + GO_BIGNUM_PTR p, GO_BIGNUM_PTR q, GO_BIGNUM_PTR g) +{ + struct dsa_st *d = dsa; + if ((d->p == NULL && p == NULL) + || (d->q == NULL && q == NULL) + || (d->g == NULL && g == NULL)) + return 0; + + if (p != NULL) { + go_openssl_BN_free(d->p); + d->p = p; + } + if (q != NULL) { + go_openssl_BN_free(d->q); + d->q = q; + } + if (g != NULL) { + go_openssl_BN_free(d->g); + d->g = g; + } + + return 1; +} + +void go_openssl_DSA_get0_key_backport(const GO_DSA_PTR dsa, + GO_BIGNUM_PTR *pub_key, GO_BIGNUM_PTR *priv_key) +{ + const struct dsa_st *d = dsa; + if (pub_key != NULL) + *pub_key = d->pub_key; + if (priv_key != NULL) + *priv_key = d->priv_key; +} + +int go_openssl_DSA_set0_key_backport(GO_DSA_PTR dsa, GO_BIGNUM_PTR pub_key, GO_BIGNUM_PTR priv_key) +{ + struct dsa_st *d = dsa; + if (d->pub_key == NULL && pub_key == NULL) + return 0; + + if (pub_key != NULL) { + go_openssl_BN_free(d->pub_key); + d->pub_key = pub_key; + } + if (priv_key != NULL) { + go_openssl_BN_free(d->priv_key); + d->priv_key = priv_key; + } + + return 1; +} \ No newline at end of file