1 From b110ec2277ba33e0935f3d465a5413f669d8aefc Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
3 Date: Tue, 11 Oct 2016 16:15:43 +0200
4 Subject: [PATCH] Port to OpenSSL 1.1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
9 OpenSSL 1.1.0 hid ECDSA structure internals and provided methods
12 This patch uses the methods and provides their copies in the case of
13 older OpenSSL. Because the new OpenSSL API, ECDSA_SIG_set0(), cannot
14 set curve parameters individually and ECDSA_SIG_get0() returns yet
15 another reference, it's necessary to duplicate the other unchanged
16 paramater when calling set_r() or set_s().
18 This patch also stops exporting ECDSA_METHOD functions that were
19 removed from the new OpenSSL.
23 Signed-off-by: Petr Písař <ppisar@redhat.com>
25 ECDSA.xs | 105 ++++++++++++++++++++++++++++++++++++++++--------
26 t/Crypt-OpenSSL-ECDSA.t | 13 +++++-
27 2 files changed, 100 insertions(+), 18 deletions(-)
29 diff --git a/ECDSA.xs b/ECDSA.xs
30 index 4016368..3d6e2d1 100644
35 #include <openssl/ecdsa.h>
36 #include <openssl/err.h>
37 +#include <openssl/bn.h>
39 #include "const-c.inc"
42 +#if OPENSSL_VERSION_NUMBER >= 0x10100000L
43 +#include <openssl/ec.h>
45 +/* ECDSA_SIG_get0() and ECDSA_SIG_set0() copied from OpenSSL 1.1.0b. */
46 +static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr,
47 + const BIGNUM **ps) {
54 +static int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
56 + if (r == NULL || s == NULL)
58 + BN_clear_free(sig->r);
59 + BN_clear_free(sig->s);
66 MODULE = Crypt::OpenSSL::ECDSA PACKAGE = Crypt::OpenSSL::ECDSA
69 @@ -17,7 +43,9 @@ INCLUDE: const-xs.inc
72 ERR_load_crypto_strings();
73 +#if OPENSSL_VERSION_NUMBER >= 0x10002000L && OPENSSL_VERSION_NUMBER < 0x10100000L
74 ERR_load_ECDSA_strings();
79 @@ -61,10 +89,16 @@ ECDSA_do_verify(const unsigned char *dgst, const ECDSA_SIG *sig, EC_KEY* eckey);
83 -# These ECDSA_METHOD functions only became available in 1.0.2
84 +# These ECDSA_METHOD functions only became available in 1.0.2,
85 +# but some of them removed again in 1.1.0.
87 #if OPENSSL_VERSION_NUMBER >= 0x10002000L
90 +ECDSA_size(const EC_KEY *eckey)
92 +#if OPENSSL_VERSION_NUMBER < 0x10100000L
97 @@ -77,9 +111,6 @@ ECDSA_get_default_method()
99 ECDSA_set_method(EC_KEY *eckey, const ECDSA_METHOD *meth)
102 -ECDSA_size(const EC_KEY *eckey)
105 ECDSA_METHOD_new(ECDSA_METHOD *ecdsa_method=0)
107 @@ -95,7 +126,7 @@ ECDSA_METHOD_set_name(ECDSA_METHOD *ecdsa_method, char *name)
109 ERR_load_ECDSA_strings()
116 @@ -135,11 +166,13 @@ SV *
124 to = malloc(sizeof(char) * 128);
125 - len = BN_bn2bin(ecdsa_sig->r, to);
126 + ECDSA_SIG_get0(ecdsa_sig, &r, NULL);
127 + len = BN_bn2bin(r, to);
128 RETVAL = newSVpvn((const char*)to, len);
131 @@ -149,11 +182,13 @@ SV *
139 to = malloc(sizeof(char) * 128);
140 - len = BN_bn2bin(ecdsa_sig->s, to);
141 + ECDSA_SIG_get0(ecdsa_sig, NULL, &s);
142 + len = BN_bn2bin(s, to);
143 RETVAL = newSVpvn((const char*)to, len);
146 @@ -164,26 +199,62 @@ set_r(ecdsa_sig, r_SV)
155 + const BIGNUM *old_s;
157 - s = SvPV(r_SV, len);
159 - BN_free(ecdsa_sig->r);
160 - ecdsa_sig->r = BN_bin2bn((const unsigned char *)s, len, NULL);
161 + string = SvPV(r_SV, len);
162 + r = BN_bin2bn((const unsigned char *)string, len, NULL);
164 + croak("Could not convert ECDSA parameter string to big number");
165 + ECDSA_SIG_get0(ecdsa_sig, NULL, &old_s);
166 + if (NULL == old_s) {
173 + croak("Could not duplicate unchanged ECDSA parameter");
175 + if (!ECDSA_SIG_set0(ecdsa_sig, r, s)) {
178 + croak("Could not store ECDSA parameters");
182 set_s(ecdsa_sig, s_SV)
191 + const BIGNUM *old_r;
193 - s = SvPV(s_SV, len);
195 - BN_free(ecdsa_sig->s);
196 - ecdsa_sig->s = BN_bin2bn((const unsigned char *)s, len, NULL);
197 + string = SvPV(s_SV, len);
198 + s = BN_bin2bn((const unsigned char *)string, len, NULL);
200 + croak("Could not convert ECDSA parameter string to big number");
201 + ECDSA_SIG_get0(ecdsa_sig, &old_r, NULL);
202 + if (NULL == old_r) {
209 + croak("Could not duplicate unchanged ECDSA parameter");
211 + if (!ECDSA_SIG_set0(ecdsa_sig, r, s)) {
214 + croak("Could not store ECDSA parameters");
219 diff --git a/t/Crypt-OpenSSL-ECDSA.t b/t/Crypt-OpenSSL-ECDSA.t
220 index 7ab584f..3c02025 100644
221 --- a/t/Crypt-OpenSSL-ECDSA.t
222 +++ b/t/Crypt-OpenSSL-ECDSA.t
227 -use Test::More tests => 21;
228 +use Test::More tests => 25;
229 BEGIN { use_ok('Crypt::OpenSSL::ECDSA'); use_ok('Crypt::OpenSSL::EC'); };
232 @@ -77,6 +77,17 @@ $ret = Crypt::OpenSSL::ECDSA::ECDSA_do_verify($digest, $sig, $key);
236 +# Test a signature can be built from scratch
237 +$sig = Crypt::OpenSSL::ECDSA::ECDSA_SIG->new();
238 +ok($sig, 'Empty Crypt::OpenSSL::ECDSA::ECDSA_SIG object created');
239 +eval { $sig->set_r($r); };
240 +ok(!$@, 'R parameter set');
241 +eval { $sig->set_s($s); };
242 +ok(!$@, 'S parameter set');
243 +$ret = Crypt::OpenSSL::ECDSA::ECDSA_do_verify($digest, $sig, $key);
244 +ok($ret, 'built-from-scratch signature matches');
247 # Testing signing and verifying with the _ex version
249 $sig = Crypt::OpenSSL::ECDSA::ECDSA_do_sign_ex($digest, \$dummy, \$dummy, $key);