Jeremy Harris writes:
> The ftp site:
>
> ftp://ftp.exim.org/pub/exim/exim4/test/
>
> now has RC3 of Exim 4.87 available. Built and
> signed by myself. [...]
DKIM signing fails with OpenSSL or rather the Base64 decoding of private
keys may fail. I get error messages in the panic.log:
2016-02-07 08:50:40 1aSK7D-0001QM-Ad DKIM: signing failed (RC -101)
Exim 4.86 works fine. The key was generated as follows:
openssl genrsa -out july2015.key 1024
openssl rsa -pubout -in july2015.key -out july2015.pub
In RC3 b64decode() fails to decode the key. But the key is valid:
# openssl rsa -in july2015.key -noout -check
RSA key ok
I've replaced the code in pdkim/pdkim.c that looks for the PEM header
and decodes the key data with functions from OpenSSL. Here's an example
that wraps the full PEM data in a memory BIO and then decodes the data:
BIO *bio = BIO_new_mem_buf(privkey_pem, -1);
if (bio != NULL) {
RSA *rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
BIO_free(bio);
}
BIO_new_mem_buf() and PEM_read_bio_RSAPrivateKey() are available since
OpenSSL 0.9.5 and 0.9.1 respectively.
Since Exim RC3 was released the code, that I've changed, was moved to
exim_rsa_signing_init() in the RSA_OPENSSL section of pdkim/rsa.c and
there's similar code in the RSA_GCRYPT section.
I use Slackware64-current with OpenSSL 1.0.2f.
Here's the patch that I use with RC3:
--- src/pdkim/pdkim.c.orig 2016-01-18 17:54:45.000000000 +0100
+++ src/pdkim/pdkim.c 2016-02-07 10:42:14.024148978 +0100
@@ -1866,8 +1866,7 @@
{
#ifdef RSA_OPENSSL
RSA * rsa;
- uschar * p, * q;
- int len;
+ BIO * bio;
#elif defined(RSA_GNUTLS)
gnutls_x509_privkey_t rsa;
gnutls_datum_t k;
@@ -1878,14 +1877,12 @@
/* Import private key */
#ifdef RSA_OPENSSL
- if ( !(p = Ustrstr(sig->rsa_privkey, "-----BEGIN RSA PRIVATE KEY-----"))
- || !(q = Ustrstr(p+=31, "-----END RSA PRIVATE KEY-----"))
- )
+ bio = BIO_new_mem_buf(sig->rsa_privkey, -1);
+ if (bio == NULL)
return PDKIM_ERR_RSA_PRIVKEY;
- *q = '\0';
- if ( (len = b64decode(p, &p)) < 0
- || !(rsa = d2i_RSAPrivateKey(NULL, CUSS &p, len))
- )
+ rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
+ BIO_free(bio);
+ if (rsa == NULL)
/*XXX todo: get errstring from library */
return PDKIM_ERR_RSA_PRIVKEY;