]>
Commit | Line | Data |
---|---|---|
c2dfe80a AM |
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 | |
5 | MIME-Version: 1.0 | |
6 | Content-Type: text/plain; charset=UTF-8 | |
7 | Content-Transfer-Encoding: 8bit | |
8 | ||
9 | OpenSSL 1.1.0 hid ECDSA structure internals and provided methods | |
10 | instead. | |
11 | ||
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(). | |
17 | ||
18 | This patch also stops exporting ECDSA_METHOD functions that were | |
19 | removed from the new OpenSSL. | |
20 | ||
21 | CPAN RT#118330 | |
22 | ||
23 | Signed-off-by: Petr Písař <ppisar@redhat.com> | |
24 | --- | |
25 | ECDSA.xs | 105 ++++++++++++++++++++++++++++++++++++++++-------- | |
26 | t/Crypt-OpenSSL-ECDSA.t | 13 +++++- | |
27 | 2 files changed, 100 insertions(+), 18 deletions(-) | |
28 | ||
29 | diff --git a/ECDSA.xs b/ECDSA.xs | |
30 | index 4016368..3d6e2d1 100644 | |
31 | --- a/ECDSA.xs | |
32 | +++ b/ECDSA.xs | |
33 | @@ -7,9 +7,35 @@ | |
34 | ||
35 | #include <openssl/ecdsa.h> | |
36 | #include <openssl/err.h> | |
37 | +#include <openssl/bn.h> | |
38 | ||
39 | #include "const-c.inc" | |
40 | ||
41 | + | |
42 | +#if OPENSSL_VERSION_NUMBER >= 0x10100000L | |
43 | +#include <openssl/ec.h> | |
44 | +#else | |
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) { | |
48 | + if (pr != NULL) | |
49 | + *pr = sig->r; | |
50 | + if (ps != NULL) | |
51 | + *ps = sig->s; | |
52 | +} | |
53 | + | |
54 | +static int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) | |
55 | +{ | |
56 | + if (r == NULL || s == NULL) | |
57 | + return 0; | |
58 | + BN_clear_free(sig->r); | |
59 | + BN_clear_free(sig->s); | |
60 | + sig->r = r; | |
61 | + sig->s = s; | |
62 | + return 1; | |
63 | +} | |
64 | +#endif | |
65 | + | |
66 | MODULE = Crypt::OpenSSL::ECDSA PACKAGE = Crypt::OpenSSL::ECDSA | |
67 | ||
68 | PROTOTYPES: ENABLE | |
69 | @@ -17,7 +43,9 @@ INCLUDE: const-xs.inc | |
70 | ||
71 | BOOT: | |
72 | ERR_load_crypto_strings(); | |
73 | +#if OPENSSL_VERSION_NUMBER >= 0x10002000L && OPENSSL_VERSION_NUMBER < 0x10100000L | |
74 | ERR_load_ECDSA_strings(); | |
75 | +#endif | |
76 | ||
77 | #ECDSA_SIG * | |
78 | #ECDSA_SIG_new() | |
79 | @@ -61,10 +89,16 @@ ECDSA_do_verify(const unsigned char *dgst, const ECDSA_SIG *sig, EC_KEY* eckey); | |
80 | OUTPUT: | |
81 | RETVAL | |
82 | ||
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. | |
86 | ||
87 | #if OPENSSL_VERSION_NUMBER >= 0x10002000L | |
88 | ||
89 | +int | |
90 | +ECDSA_size(const EC_KEY *eckey) | |
91 | + | |
92 | +#if OPENSSL_VERSION_NUMBER < 0x10100000L | |
93 | + | |
94 | const ECDSA_METHOD * | |
95 | ECDSA_OpenSSL() | |
96 | ||
97 | @@ -77,9 +111,6 @@ ECDSA_get_default_method() | |
98 | int | |
99 | ECDSA_set_method(EC_KEY *eckey, const ECDSA_METHOD *meth) | |
100 | ||
101 | -int | |
102 | -ECDSA_size(const EC_KEY *eckey) | |
103 | - | |
104 | ECDSA_METHOD * | |
105 | ECDSA_METHOD_new(ECDSA_METHOD *ecdsa_method=0) | |
106 | ||
107 | @@ -95,7 +126,7 @@ ECDSA_METHOD_set_name(ECDSA_METHOD *ecdsa_method, char *name) | |
108 | void | |
109 | ERR_load_ECDSA_strings() | |
110 | ||
111 | - | |
112 | +#endif | |
113 | #endif | |
114 | ||
115 | ||
116 | @@ -135,11 +166,13 @@ SV * | |
117 | get_r(ecdsa_sig) | |
118 | ECDSA_SIG *ecdsa_sig | |
119 | PREINIT: | |
120 | + const BIGNUM *r; | |
121 | unsigned char *to; | |
122 | STRLEN len; | |
123 | CODE: | |
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); | |
129 | free(to); | |
130 | OUTPUT: | |
131 | @@ -149,11 +182,13 @@ SV * | |
132 | get_s(ecdsa_sig) | |
133 | ECDSA_SIG *ecdsa_sig | |
134 | PREINIT: | |
135 | + const BIGNUM *s; | |
136 | unsigned char *to; | |
137 | STRLEN len; | |
138 | CODE: | |
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); | |
144 | free(to); | |
145 | OUTPUT: | |
146 | @@ -164,26 +199,62 @@ set_r(ecdsa_sig, r_SV) | |
147 | ECDSA_SIG *ecdsa_sig | |
148 | SV * r_SV | |
149 | PREINIT: | |
150 | - char *s; | |
151 | + char *string; | |
152 | STRLEN len; | |
153 | + BIGNUM *r; | |
154 | + BIGNUM *s; | |
155 | + const BIGNUM *old_s; | |
156 | CODE: | |
157 | - s = SvPV(r_SV, len); | |
158 | - if (ecdsa_sig->r) | |
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); | |
163 | + if (NULL == r) | |
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) { | |
167 | + s = BN_new(); | |
168 | + } else { | |
169 | + s = BN_dup(old_s); | |
170 | + } | |
171 | + if (NULL == s) { | |
172 | + BN_free(r); | |
173 | + croak("Could not duplicate unchanged ECDSA parameter"); | |
174 | + } | |
175 | + if (!ECDSA_SIG_set0(ecdsa_sig, r, s)) { | |
176 | + BN_free(r); | |
177 | + BN_free(s); | |
178 | + croak("Could not store ECDSA parameters"); | |
179 | + } | |
180 | ||
181 | void | |
182 | set_s(ecdsa_sig, s_SV) | |
183 | ECDSA_SIG *ecdsa_sig | |
184 | SV * s_SV | |
185 | PREINIT: | |
186 | - char *s; | |
187 | + char *string; | |
188 | STRLEN len; | |
189 | + BIGNUM *r; | |
190 | + BIGNUM *s; | |
191 | + const BIGNUM *old_r; | |
192 | CODE: | |
193 | - s = SvPV(s_SV, len); | |
194 | - if (ecdsa_sig->s) | |
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); | |
199 | + if (NULL == s) | |
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) { | |
203 | + r = BN_new(); | |
204 | + } else { | |
205 | + r = BN_dup(old_r); | |
206 | + } | |
207 | + if (NULL == r) { | |
208 | + BN_free(s); | |
209 | + croak("Could not duplicate unchanged ECDSA parameter"); | |
210 | + } | |
211 | + if (!ECDSA_SIG_set0(ecdsa_sig, r, s)) { | |
212 | + BN_free(r); | |
213 | + BN_free(s); | |
214 | + croak("Could not store ECDSA parameters"); | |
215 | + } | |
216 | ||
217 | ||
218 | ||
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 | |
223 | @@ -6,7 +6,7 @@ | |
224 | use strict; | |
225 | use warnings; | |
226 | ||
227 | -use Test::More tests => 21; | |
228 | +use Test::More tests => 25; | |
229 | BEGIN { use_ok('Crypt::OpenSSL::ECDSA'); use_ok('Crypt::OpenSSL::EC'); }; | |
230 | ||
231 | ||
232 | @@ -77,6 +77,17 @@ $ret = Crypt::OpenSSL::ECDSA::ECDSA_do_verify($digest, $sig, $key); | |
233 | ok($ret); | |
234 | undef $sig; | |
235 | ||
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'); | |
245 | +undef $sig; | |
246 | + | |
247 | # Testing signing and verifying with the _ex version | |
248 | my $dummy = 0; | |
249 | $sig = Crypt::OpenSSL::ECDSA::ECDSA_do_sign_ex($digest, \$dummy, \$dummy, $key); | |
250 | -- | |
251 | 2.7.4 | |
252 |