control: tags -1 patch

On 2016-06-26 12:22:30 [+0200], Kurt Roeckx wrote:
> There is a libssl-dev package available in experimental that contains a recent
> snapshot, I suggest you try building against that to see if everything works.

two patches attached. The testsuite passes.
Functions like set_p() need to query old q & g because with openssl
1.1.0 it is no longer possible to assign only one of them. That means
for the first assignment I have two dummy arguments which are later
overwritten. The better way would be to change the perl API to also
assign p, q and g at once. It also not possible to assign the private
key without the public key. Is this possible?

I needed to extend the length of the seed argument (in the testsuite)
for generate_parameters because 3 ("foo") is too small and openssl 1.1.0
no longer ignores this invalid argument.

> Kurt

Sebastian
>From 6efaaad1f6b5ed33b5079d2f116db8795a708d8c Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <[email protected]>
Date: Mon, 3 Oct 2016 12:32:38 +0000
Subject: [PATCH 1/2] libcrypt-openssl-dsa-perl: add openssl 1.1.0 support

Signed-off-by: Sebastian Andrzej Siewior <[email protected]>
---
 DSA.xs | 185 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 170 insertions(+), 15 deletions(-)

diff --git a/DSA.xs b/DSA.xs
index 00e6b270a9de..25810e539338 100755
--- a/DSA.xs
+++ b/DSA.xs
@@ -14,6 +14,95 @@ extern "C" {
 #include <openssl/dsa.h>
 #include <openssl/ssl.h>
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000
+static void DSA_get0_pqg(const DSA *d,
+                         const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
+{
+    if (p != NULL)
+        *p = d->p;
+    if (q != NULL)
+        *q = d->q;
+    if (g != NULL)
+        *g = d->g;
+}
+
+static int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
+{
+    /* If the fields p, q and g in d are NULL, the corresponding input
+     * parameters MUST be non-NULL.
+     */
+    if ((d->p == NULL && p == NULL)
+        || (d->q == NULL && q == NULL)
+        || (d->g == NULL && g == NULL))
+        return 0;
+
+    if (p != NULL) {
+        BN_free(d->p);
+        d->p = p;
+    }
+    if (q != NULL) {
+        BN_free(d->q);
+        d->q = q;
+    }
+    if (g != NULL) {
+        BN_free(d->g);
+        d->g = g;
+    }
+
+    return 1;
+}
+
+static int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
+{
+    /* If the field pub_key in d is NULL, the corresponding input
+     *       * parameters MUST be non-NULL.  The priv_key field may
+     *             * be left NULL.
+     *                   */
+    if (d->pub_key == NULL && pub_key == NULL)
+        return 0;
+
+    if (pub_key != NULL) {
+        BN_free(d->pub_key);
+        d->pub_key = pub_key;
+    }
+    if (priv_key != NULL) {
+        BN_free(d->priv_key);
+        d->priv_key = priv_key;
+    }
+
+    return 1;
+}
+
+static void DSA_get0_key(const DSA *d,
+                         const BIGNUM **pub_key, const BIGNUM **priv_key)
+{
+    if (pub_key != NULL)
+        *pub_key = d->pub_key;
+    if (priv_key != NULL)
+        *priv_key = d->priv_key;
+}
+
+static void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
+{
+    if (pr != NULL)
+        *pr = sig->r;
+    if (ps != NULL)
+        *ps = sig->s;
+}
+
+static int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s)
+{
+    if (r == NULL || s == NULL)
+        return 0;
+    BN_clear_free(sig->r);
+    BN_clear_free(sig->s);
+    sig->r = r;
+    sig->s = s;
+    return 1;
+}
+
+#endif
+
 #ifdef __cplusplus
 }
 #endif
@@ -52,9 +141,12 @@ generate_parameters(CLASS, bits, seed = NULL)
         if (seed) {
           seedpv = SvPV(seed, seed_len);
         }
-        dsa = DSA_generate_parameters(bits, seedpv, seed_len, NULL, NULL, NULL, NULL);
+
+        dsa = DSA_new();
         if (!dsa)
           croak("%s", ERR_reason_error_string(ERR_get_error()));
+        if (!DSA_generate_parameters_ex(dsa, bits, seedpv, seed_len, NULL, NULL, NULL))
+            croak("%s", ERR_reason_error_string(ERR_get_error()));
         RETVAL = dsa;
     OUTPUT:
         RETVAL
@@ -259,9 +351,11 @@ get_p(dsa)
     PREINIT:
         char *to;
         int len;
+        const BIGNUM *p;
     CODE:
         to = malloc(sizeof(char) * 128);
-        len = BN_bn2bin(dsa->p, to);
+        DSA_get0_pqg(dsa, &p, NULL, NULL);
+        len = BN_bn2bin(p, to);
         RETVAL = newSVpvn(to, len);
         free(to);
     OUTPUT:
@@ -273,9 +367,11 @@ get_q(dsa)
     PREINIT:
         char *to;
         int len;
+        const BIGNUM *q;
     CODE:
         to = malloc(sizeof(char) * 20);
-        len = BN_bn2bin(dsa->q, to);
+        DSA_get0_pqg(dsa, NULL, &q, NULL);
+        len = BN_bn2bin(q, to);
         RETVAL = newSVpvn(to, len);
         free(to);
     OUTPUT:
@@ -287,9 +383,11 @@ get_g(dsa)
     PREINIT:
         char *to;
         int len;
+        const BIGNUM *g;
     CODE:
         to = malloc(sizeof(char) * 128);
-        len = BN_bn2bin(dsa->g, to);
+        DSA_get0_pqg(dsa, NULL, NULL, &g);
+        len = BN_bn2bin(g, to);
         RETVAL = newSVpvn(to, len);
         free(to);
     OUTPUT:
@@ -301,9 +399,11 @@ get_pub_key(dsa)
     PREINIT:
         char *to;
         int len;
+        const BIGNUM *pub_key;
     CODE:
         to = malloc(sizeof(char) * 128);
-        len = BN_bn2bin(dsa->pub_key, to);
+        DSA_get0_key(dsa, &pub_key, NULL);
+        len = BN_bn2bin(pub_key, to);
         RETVAL = newSVpvn(to, len);
         free(to);
     OUTPUT:
@@ -315,9 +415,11 @@ get_priv_key(dsa)
     PREINIT:
         char *to;
         int len;
+        const BIGNUM *priv_key;
     CODE:
         to = malloc(sizeof(char) * 128);
-        len = BN_bn2bin(dsa->priv_key, to);
+        DSA_get0_key(dsa, NULL, &priv_key);
+        len = BN_bn2bin(priv_key, to);
         RETVAL = newSVpvn(to, len);
         free(to);
     OUTPUT:
@@ -329,9 +431,17 @@ set_p(dsa, p_SV)
         SV * p_SV
     PREINIT:
         int len;
+        const BIGNUM *old_q, *old_g;
+        BIGNUM *new_q = NULL, *new_g = NULL;
     CODE:
+        DSA_get0_pqg(dsa, NULL, &old_q, &old_g);
+        if (!old_q)
+                new_q = BN_new();
+        if (!old_g)
+                new_g = BN_new();
         len = SvCUR(p_SV);
-        dsa->p = BN_bin2bn(SvPV(p_SV, len), len, NULL);
+        if (!DSA_set0_pqg(dsa, BN_bin2bn(SvPV(p_SV, len), len, NULL), new_q, new_g))
+          croak("DSA_set0_pqg() failed");
 
 void
 set_q(dsa, q_SV)
@@ -339,9 +449,17 @@ set_q(dsa, q_SV)
         SV * q_SV
     PREINIT:
         int len;
+        const BIGNUM *old_p, *old_g;
+        BIGNUM *new_p = NULL, *new_g = NULL;
     CODE:
+        DSA_get0_pqg(dsa, &old_p, NULL, &old_g);
+        if (!old_p)
+                new_p = BN_new();
+        if (!old_g)
+                new_g = BN_new();
         len = SvCUR(q_SV);
-        dsa->q = BN_bin2bn(SvPV(q_SV, len), len, NULL);
+        if (!DSA_set0_pqg(dsa, new_p, BN_bin2bn(SvPV(q_SV, len), len, NULL), new_g))
+          croak("DSA_set0_pqg() failed");
 
 void
 set_g(dsa, g_SV)
@@ -349,9 +467,17 @@ set_g(dsa, g_SV)
         SV * g_SV
     PREINIT:
         int len;
+        const BIGNUM *old_p, *old_q;
+        BIGNUM *new_p = NULL, *new_q = NULL;
     CODE:
+        DSA_get0_pqg(dsa, &old_p, &old_q, NULL);
+        if (!old_p)
+                new_p = BN_new();
+        if (!old_q)
+                new_q = BN_new();
         len = SvCUR(g_SV);
-        dsa->g = BN_bin2bn(SvPV(g_SV, len), len, NULL);
+        if (!DSA_set0_pqg(dsa, new_p, new_q, BN_bin2bn(SvPV(g_SV, len), len, NULL)))
+          croak("DSA_set0_pqg() failed");
 
 void
 set_pub_key(dsa, pub_key_SV)
@@ -361,7 +487,8 @@ set_pub_key(dsa, pub_key_SV)
         int len;
     CODE:
         len = SvCUR(pub_key_SV);
-        dsa->pub_key = BN_bin2bn(SvPV(pub_key_SV, len), len, NULL);
+        if (!DSA_set0_key(dsa, BN_bin2bn(SvPV(pub_key_SV, len), len, NULL), NULL))
+          croak("DSA_set0_key() failed");
 
 void
 set_priv_key(dsa, priv_key_SV)
@@ -369,9 +496,16 @@ set_priv_key(dsa, priv_key_SV)
         SV * priv_key_SV
     PREINIT:
         int len;
+        const BIGNUM *old_pub;
+        BIGNUM *new_pub = NULL;
     CODE:
         len = SvCUR(priv_key_SV);
-        dsa->priv_key = BN_bin2bn(SvPV(priv_key_SV, len), len, NULL);
+        DSA_get0_key(dsa, &old_pub, NULL);
+        if (!old_pub)
+            new_pub = BN_new();
+
+        if (!DSA_set0_key(dsa, new_pub, BN_bin2bn(SvPV(priv_key_SV, len), len, NULL)))
+          croak("DSA_set0_key() failed");
 
 MODULE = Crypt::OpenSSL::DSA    PACKAGE = Crypt::OpenSSL::DSA::Signature
 
@@ -395,9 +529,11 @@ get_r(dsa_sig)
     PREINIT:
         char *to;
         int len;
+        const BIGNUM *r;
     CODE:
         to = malloc(sizeof(char) * 128);
-        len = BN_bn2bin(dsa_sig->r, to);
+        DSA_SIG_get0(dsa_sig, &r, NULL);
+        len = BN_bn2bin(r, to);
         RETVAL = newSVpvn(to, len);
         free(to);
     OUTPUT:
@@ -409,9 +545,11 @@ get_s(dsa_sig)
     PREINIT:
         char *to;
         int len;
+        const BIGNUM *s;
     CODE:
         to = malloc(sizeof(char) * 128);
-        len = BN_bn2bin(dsa_sig->s, to);
+        DSA_SIG_get0(dsa_sig, NULL, &s);
+        len = BN_bn2bin(s, to);
         RETVAL = newSVpvn(to, len);
         free(to);
     OUTPUT:
@@ -423,9 +561,17 @@ set_r(dsa_sig, r_SV)
         SV * r_SV
     PREINIT:
         int len;
+        const BIGNUM *old_s;
+        BIGNUM *new_s;
     CODE:
+        DSA_SIG_get0(dsa_sig, NULL, &old_s);
+        if (old_s)
+                new_s = BN_dup(old_s);
+       else
+                new_s = BN_new();
         len = SvCUR(r_SV);
-        dsa_sig->r = BN_bin2bn(SvPV(r_SV, len), len, NULL);
+        if (!DSA_SIG_set0(dsa_sig, BN_bin2bn(SvPV(r_SV, len), len, NULL), new_s))
+          croak("DSA_SIG_set0() failed");
 
 void
 set_s(dsa_sig, s_SV)
@@ -433,6 +579,15 @@ set_s(dsa_sig, s_SV)
         SV * s_SV
     PREINIT:
         int len;
+        const BIGNUM *old_r;
+        BIGNUM *new_r;
     CODE:
+        DSA_SIG_get0(dsa_sig, &old_r, NULL);
+        if (old_r)
+                new_r = BN_dup(old_r);
+       else
+                new_r = BN_new();
+
         len = SvCUR(s_SV);
-        dsa_sig->s = BN_bin2bn(SvPV(s_SV, len), len, NULL);
+        if (!DSA_SIG_set0(dsa_sig, new_r, BN_bin2bn(SvPV(s_SV, len), len, NULL)))
+          croak("DSA_SIG_set0() failed");
-- 
2.9.3

>From ea1e9a9a4adf5d8510004cf1acba203db6bc13a1 Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <[email protected]>
Date: Mon, 3 Oct 2016 16:11:00 +0000
Subject: [PATCH 2/2] test: increase seed

As of openssl 1.1.0 a too small seed is no longer ignored. from the
manpage:

|bits is the length of the prime p to be generated.  For lengths under 2048
|bits, the length of q is 160 bits; for lengths greater than or equal to 2048
|bits, the length of q is set to 256 bits.
|
|If seed is NULL, the primes will be generated at random.  If seed_len is
|less than the length of q, an error is returned.

The testsuite is adjusted.

Signed-off-by: Sebastian Andrzej Siewior <[email protected]>
---
 t/10-selftest.t       | 2 +-
 t/90-openssl-compat.t | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/t/10-selftest.t b/t/10-selftest.t
index 54b517a04568..1435cc8797d0 100755
--- a/t/10-selftest.t
+++ b/t/10-selftest.t
@@ -9,7 +9,7 @@ BEGIN { plan tests => 30 }
 
 my $message = "foo bar";
 
-my $dsa = Crypt::OpenSSL::DSA->generate_parameters( 512, "foo" );
+my $dsa = Crypt::OpenSSL::DSA->generate_parameters( 512, "foofoofoofoofoofoofo");
 
 $dsa->generate_key;
 
diff --git a/t/90-openssl-compat.t b/t/90-openssl-compat.t
index eba43fe1a9f8..6347710a3d9d 100755
--- a/t/90-openssl-compat.t
+++ b/t/90-openssl-compat.t
@@ -25,7 +25,7 @@ else {
   }
 my $why_skip = $HAS_SHA1 ? "Need openssl binary in path" : "Need Digest::SHA to test";
 
-my $dsa = Crypt::OpenSSL::DSA->generate_parameters( 512, "foo" );
+my $dsa = Crypt::OpenSSL::DSA->generate_parameters( 512, "foofoofoofoofoofoofo" );
 $dsa->generate_key;
 
 ok($dsa->write_pub_key("dsa.pub.pem"), 1);
-- 
2.9.3

Reply via email to