You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
253 lines
6.8 KiB
253 lines
6.8 KiB
5 years ago
|
From b110ec2277ba33e0935f3d465a5413f669d8aefc Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
|
||
|
Date: Tue, 11 Oct 2016 16:15:43 +0200
|
||
|
Subject: [PATCH] Port to OpenSSL 1.1.0
|
||
|
MIME-Version: 1.0
|
||
|
Content-Type: text/plain; charset=UTF-8
|
||
|
Content-Transfer-Encoding: 8bit
|
||
|
|
||
|
OpenSSL 1.1.0 hid ECDSA structure internals and provided methods
|
||
|
instead.
|
||
|
|
||
|
This patch uses the methods and provides their copies in the case of
|
||
|
older OpenSSL. Because the new OpenSSL API, ECDSA_SIG_set0(), cannot
|
||
|
set curve parameters individually and ECDSA_SIG_get0() returns yet
|
||
|
another reference, it's necessary to duplicate the other unchanged
|
||
|
paramater when calling set_r() or set_s().
|
||
|
|
||
|
This patch also stops exporting ECDSA_METHOD functions that were
|
||
|
removed from the new OpenSSL.
|
||
|
|
||
|
CPAN RT#118330
|
||
|
|
||
|
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||
|
---
|
||
|
ECDSA.xs | 105 ++++++++++++++++++++++++++++++++++++++++--------
|
||
|
t/Crypt-OpenSSL-ECDSA.t | 13 +++++-
|
||
|
2 files changed, 100 insertions(+), 18 deletions(-)
|
||
|
|
||
|
diff --git a/ECDSA.xs b/ECDSA.xs
|
||
|
index 4016368..3d6e2d1 100644
|
||
|
--- a/ECDSA.xs
|
||
|
+++ b/ECDSA.xs
|
||
|
@@ -7,9 +7,35 @@
|
||
|
|
||
|
#include <openssl/ecdsa.h>
|
||
|
#include <openssl/err.h>
|
||
|
+#include <openssl/bn.h>
|
||
|
|
||
|
#include "const-c.inc"
|
||
|
|
||
|
+
|
||
|
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||
|
+#include <openssl/ec.h>
|
||
|
+#else
|
||
|
+/* ECDSA_SIG_get0() and ECDSA_SIG_set0() copied from OpenSSL 1.1.0b. */
|
||
|
+static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr,
|
||
|
+ const BIGNUM **ps) {
|
||
|
+ if (pr != NULL)
|
||
|
+ *pr = sig->r;
|
||
|
+ if (ps != NULL)
|
||
|
+ *ps = sig->s;
|
||
|
+}
|
||
|
+
|
||
|
+static int ECDSA_SIG_set0(ECDSA_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
|
||
|
+
|
||
|
MODULE = Crypt::OpenSSL::ECDSA PACKAGE = Crypt::OpenSSL::ECDSA
|
||
|
|
||
|
PROTOTYPES: ENABLE
|
||
|
@@ -17,7 +43,9 @@ INCLUDE: const-xs.inc
|
||
|
|
||
|
BOOT:
|
||
|
ERR_load_crypto_strings();
|
||
|
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L && OPENSSL_VERSION_NUMBER < 0x10100000L
|
||
|
ERR_load_ECDSA_strings();
|
||
|
+#endif
|
||
|
|
||
|
#ECDSA_SIG *
|
||
|
#ECDSA_SIG_new()
|
||
|
@@ -61,10 +89,16 @@ ECDSA_do_verify(const unsigned char *dgst, const ECDSA_SIG *sig, EC_KEY* eckey);
|
||
|
OUTPUT:
|
||
|
RETVAL
|
||
|
|
||
|
-# These ECDSA_METHOD functions only became available in 1.0.2
|
||
|
+# These ECDSA_METHOD functions only became available in 1.0.2,
|
||
|
+# but some of them removed again in 1.1.0.
|
||
|
|
||
|
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||
|
|
||
|
+int
|
||
|
+ECDSA_size(const EC_KEY *eckey)
|
||
|
+
|
||
|
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||
|
+
|
||
|
const ECDSA_METHOD *
|
||
|
ECDSA_OpenSSL()
|
||
|
|
||
|
@@ -77,9 +111,6 @@ ECDSA_get_default_method()
|
||
|
int
|
||
|
ECDSA_set_method(EC_KEY *eckey, const ECDSA_METHOD *meth)
|
||
|
|
||
|
-int
|
||
|
-ECDSA_size(const EC_KEY *eckey)
|
||
|
-
|
||
|
ECDSA_METHOD *
|
||
|
ECDSA_METHOD_new(ECDSA_METHOD *ecdsa_method=0)
|
||
|
|
||
|
@@ -95,7 +126,7 @@ ECDSA_METHOD_set_name(ECDSA_METHOD *ecdsa_method, char *name)
|
||
|
void
|
||
|
ERR_load_ECDSA_strings()
|
||
|
|
||
|
-
|
||
|
+#endif
|
||
|
#endif
|
||
|
|
||
|
|
||
|
@@ -135,11 +166,13 @@ SV *
|
||
|
get_r(ecdsa_sig)
|
||
|
ECDSA_SIG *ecdsa_sig
|
||
|
PREINIT:
|
||
|
+ const BIGNUM *r;
|
||
|
unsigned char *to;
|
||
|
STRLEN len;
|
||
|
CODE:
|
||
|
to = malloc(sizeof(char) * 128);
|
||
|
- len = BN_bn2bin(ecdsa_sig->r, to);
|
||
|
+ ECDSA_SIG_get0(ecdsa_sig, &r, NULL);
|
||
|
+ len = BN_bn2bin(r, to);
|
||
|
RETVAL = newSVpvn((const char*)to, len);
|
||
|
free(to);
|
||
|
OUTPUT:
|
||
|
@@ -149,11 +182,13 @@ SV *
|
||
|
get_s(ecdsa_sig)
|
||
|
ECDSA_SIG *ecdsa_sig
|
||
|
PREINIT:
|
||
|
+ const BIGNUM *s;
|
||
|
unsigned char *to;
|
||
|
STRLEN len;
|
||
|
CODE:
|
||
|
to = malloc(sizeof(char) * 128);
|
||
|
- len = BN_bn2bin(ecdsa_sig->s, to);
|
||
|
+ ECDSA_SIG_get0(ecdsa_sig, NULL, &s);
|
||
|
+ len = BN_bn2bin(s, to);
|
||
|
RETVAL = newSVpvn((const char*)to, len);
|
||
|
free(to);
|
||
|
OUTPUT:
|
||
|
@@ -164,26 +199,62 @@ set_r(ecdsa_sig, r_SV)
|
||
|
ECDSA_SIG *ecdsa_sig
|
||
|
SV * r_SV
|
||
|
PREINIT:
|
||
|
- char *s;
|
||
|
+ char *string;
|
||
|
STRLEN len;
|
||
|
+ BIGNUM *r;
|
||
|
+ BIGNUM *s;
|
||
|
+ const BIGNUM *old_s;
|
||
|
CODE:
|
||
|
- s = SvPV(r_SV, len);
|
||
|
- if (ecdsa_sig->r)
|
||
|
- BN_free(ecdsa_sig->r);
|
||
|
- ecdsa_sig->r = BN_bin2bn((const unsigned char *)s, len, NULL);
|
||
|
+ string = SvPV(r_SV, len);
|
||
|
+ r = BN_bin2bn((const unsigned char *)string, len, NULL);
|
||
|
+ if (NULL == r)
|
||
|
+ croak("Could not convert ECDSA parameter string to big number");
|
||
|
+ ECDSA_SIG_get0(ecdsa_sig, NULL, &old_s);
|
||
|
+ if (NULL == old_s) {
|
||
|
+ s = BN_new();
|
||
|
+ } else {
|
||
|
+ s = BN_dup(old_s);
|
||
|
+ }
|
||
|
+ if (NULL == s) {
|
||
|
+ BN_free(r);
|
||
|
+ croak("Could not duplicate unchanged ECDSA parameter");
|
||
|
+ }
|
||
|
+ if (!ECDSA_SIG_set0(ecdsa_sig, r, s)) {
|
||
|
+ BN_free(r);
|
||
|
+ BN_free(s);
|
||
|
+ croak("Could not store ECDSA parameters");
|
||
|
+ }
|
||
|
|
||
|
void
|
||
|
set_s(ecdsa_sig, s_SV)
|
||
|
ECDSA_SIG *ecdsa_sig
|
||
|
SV * s_SV
|
||
|
PREINIT:
|
||
|
- char *s;
|
||
|
+ char *string;
|
||
|
STRLEN len;
|
||
|
+ BIGNUM *r;
|
||
|
+ BIGNUM *s;
|
||
|
+ const BIGNUM *old_r;
|
||
|
CODE:
|
||
|
- s = SvPV(s_SV, len);
|
||
|
- if (ecdsa_sig->s)
|
||
|
- BN_free(ecdsa_sig->s);
|
||
|
- ecdsa_sig->s = BN_bin2bn((const unsigned char *)s, len, NULL);
|
||
|
+ string = SvPV(s_SV, len);
|
||
|
+ s = BN_bin2bn((const unsigned char *)string, len, NULL);
|
||
|
+ if (NULL == s)
|
||
|
+ croak("Could not convert ECDSA parameter string to big number");
|
||
|
+ ECDSA_SIG_get0(ecdsa_sig, &old_r, NULL);
|
||
|
+ if (NULL == old_r) {
|
||
|
+ r = BN_new();
|
||
|
+ } else {
|
||
|
+ r = BN_dup(old_r);
|
||
|
+ }
|
||
|
+ if (NULL == r) {
|
||
|
+ BN_free(s);
|
||
|
+ croak("Could not duplicate unchanged ECDSA parameter");
|
||
|
+ }
|
||
|
+ if (!ECDSA_SIG_set0(ecdsa_sig, r, s)) {
|
||
|
+ BN_free(r);
|
||
|
+ BN_free(s);
|
||
|
+ croak("Could not store ECDSA parameters");
|
||
|
+ }
|
||
|
|
||
|
|
||
|
|
||
|
diff --git a/t/Crypt-OpenSSL-ECDSA.t b/t/Crypt-OpenSSL-ECDSA.t
|
||
|
index 7ab584f..3c02025 100644
|
||
|
--- a/t/Crypt-OpenSSL-ECDSA.t
|
||
|
+++ b/t/Crypt-OpenSSL-ECDSA.t
|
||
|
@@ -6,7 +6,7 @@
|
||
|
use strict;
|
||
|
use warnings;
|
||
|
|
||
|
-use Test::More tests => 21;
|
||
|
+use Test::More tests => 25;
|
||
|
BEGIN { use_ok('Crypt::OpenSSL::ECDSA'); use_ok('Crypt::OpenSSL::EC'); };
|
||
|
|
||
|
|
||
|
@@ -77,6 +77,17 @@ $ret = Crypt::OpenSSL::ECDSA::ECDSA_do_verify($digest, $sig, $key);
|
||
|
ok($ret);
|
||
|
undef $sig;
|
||
|
|
||
|
+# Test a signature can be built from scratch
|
||
|
+$sig = Crypt::OpenSSL::ECDSA::ECDSA_SIG->new();
|
||
|
+ok($sig, 'Empty Crypt::OpenSSL::ECDSA::ECDSA_SIG object created');
|
||
|
+eval { $sig->set_r($r); };
|
||
|
+ok(!$@, 'R parameter set');
|
||
|
+eval { $sig->set_s($s); };
|
||
|
+ok(!$@, 'S parameter set');
|
||
|
+$ret = Crypt::OpenSSL::ECDSA::ECDSA_do_verify($digest, $sig, $key);
|
||
|
+ok($ret, 'built-from-scratch signature matches');
|
||
|
+undef $sig;
|
||
|
+
|
||
|
# Testing signing and verifying with the _ex version
|
||
|
my $dummy = 0;
|
||
|
$sig = Crypt::OpenSSL::ECDSA::ECDSA_do_sign_ex($digest, \$dummy, \$dummy, $key);
|
||
|
--
|
||
|
2.7.4
|
||
|
|