Opened 10 years ago

Closed 8 years ago

#46596 closed defect (wontfix)

openssl @1.0.1k breaks certificate signature verification

Reported by: mouse07410 (Mouse) Owned by: larryv (Lawrence Velázquez)
Priority: High Milestone:
Component: ports Version: 2.3.3
Keywords: Cc: neverpanic (Clemens Lang)
Port: openssl

Description

Current openssl-1.0.1k_0 port breaks certificate signature verification:

$ openssl version
OpenSSL 1.0.1k 8 Jan 2015
$ openssl verify -CAfile RabbitMQ_Test_CA.pem -verbose RabbitMQ_Test.pem
RabbitMQ_Test.pem: CN = RabbitMQ_Test, C = US
error 7 at 0 depth lookup:certificate signature failure
$ /usr/bin/openssl version
OpenSSL 0.9.8za 5 Jun 2014
$ /usr/bin/openssl verify -CAfile RabbitMQ_Test_CA.pem -verbose RabbitMQ_Test.pem
RabbitMQ_Test.pem: OK
$ 

Needless to say, certificates in question are correct and work fine elsewhere. They also validate just fine on the same machine/platform (Mac OS X 10.9.5 and Xcode-6.1.1) using native openssl port, as shown above. One certificate that demonstrates this problem is attached, together with its CA cert.

This is a critical problem.

Attachments (5)

RabbitMQ_Test.pem (1.3 KB) - added by mouse07410 (Mouse) 10 years ago.
Certificate that demonstrates the problem
RabbitMQ_Test_CA.pem (1.2 KB) - added by mouse07410 (Mouse) 10 years ago.
CA used to create and verify this certificate
openssl-1.0.1k.patch (662 bytes) - added by mouse07410 (Mouse) 10 years ago.
Patch that provides a reasonably secure workaround for this problem
RabbitMQ_Test_CA.dump.txt (8.0 KB) - added by mouse07410 (Mouse) 10 years ago.
Dump of ASN.1 encoding of a cert, illustrating problem: look at data at offset 20, and compare it with offsets 223 and 628.
patch-null-absent.diff (783 bytes) - added by mouse07410 (Mouse) 10 years ago.
Updated patch for signature algorithm mismatch and ASN.1 type comparison bug.

Download all attachments as: .zip

Change History (28)

Changed 10 years ago by mouse07410 (Mouse)

Attachment: RabbitMQ_Test.pem added

Certificate that demonstrates the problem

Changed 10 years ago by mouse07410 (Mouse)

Attachment: RabbitMQ_Test_CA.pem added

CA used to create and verify this certificate

comment:1 Changed 10 years ago by mouse07410 (Mouse)

Interestingly enough, the CA cert itself validates fine:

$ openssl verify -CAfile RabbitMQ_Test_CA.pem -verbose RabbitMQ_Test_CA.pem
RabbitMQ_Test_CA.pem: OK
$ 

Changed 10 years ago by mouse07410 (Mouse)

Attachment: openssl-1.0.1k.patch added

Patch that provides a reasonably secure workaround for this problem

comment:2 Changed 10 years ago by mouse07410 (Mouse)

Problem has been tracked to ASN.1 type comparison in "crypto/asn1/a_type.c". It is triggered from 1.0.1k version by the following patch:

diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c
index e06602d..fef55f8 100644 (file)
--- a/crypto/x509/x_all.c
+++ b/crypto/x509/x_all.c
@@ -72,6 +72,8 @@
 
 int X509_verify(X509 *a, EVP_PKEY *r)
        {
+       if (X509_ALGOR_cmp(a->sig_alg, a->cert_info->signature))
+               return 0;
        return(ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF),a->sig_alg,
                a->signature,a->cert_info,r));
        }

The above patch invokes "X509_ALGOR_cmp" in "crypto/asn1/x_algor.c", which in turn invokes "ASN1_TYPE_cmp" in "crypto/asn1/a_type.c", where the comparison fails because one parameter is explicit ASN.1 NULL (0x05), while the other one is empty (not present, null-pointer). So ASN.1 NULL fails to compare to NULL, and the entire comparison fails with "not equal".

I think the cause of this problem is somewhere in the certificate decoding piece, where either an explicit ASN.1 NULL gets added when it shouldn't, or the code forgets to add it when it should. Correction: after checking the actual certificate ASN.1 encoding, I found that indeed in all places but one, signature algorithm parameters part is encoded as ASN.1 NULL; and in one place the parameters part is just not present (thus decoded as null pointer). I still maintain that the two are equal. :)

The following is a reasonable secure workaround, until somebody figures why certificate parsing is screwed up:

$ diff -uw crypto/asn1/a_type.c.~1~ crypto/asn1/a_type.c
--- crypto/asn1/a_type.c.~1~	2015-01-15 09:43:14.000000000 -0500
+++ crypto/asn1/a_type.c	2015-01-17 15:12:17.000000000 -0500
@@ -117,7 +117,22 @@
 	{
 	int result = -1;
 
-	if (!a || !b || a->type != b->type) return -1;
+	if (!a || !b) {
+	  if (!a && !b) /* both types are empty (null) */
+	    return 0;
+	  /* one is null, the other is maybe ASN.1 NULL (explicit) */
+	  if (a && !b) { 
+	    if (a->type == V_ASN1_NULL)
+	      return 0;
+	  } 
+	  if (b && !a) {
+	    if (b->type == V_ASN1_NULL)
+	      return 0;
+	  }
+	  return -1; /* the non-null (present) type isn't ASN.1 NULL */
+	}
+
+	if (a->type != b->type) return -1;
 
 	switch (a->type)
 		{

I've also attached it as a patch.

For what it's worth - the same problem (and I suspect caused by the same misunderstanding leading to the same bug) is present in the latest beta (development) versions of Botan library https://botan.randombit.net, starting with 1.11.12.

Last edited 10 years ago by mouse07410 (Mouse) (previous) (diff)

comment:3 Changed 10 years ago by ryandesign (Ryan Carsten Schmidt)

Keywords: openssl removed
Owner: changed from macports-tickets@… to mww@…
Summary: openssl-1.0.1k breaks certificate signature verificationopenssl @1.0.1k breaks certificate signature verification

comment:4 Changed 10 years ago by mouse07410 (Mouse)

Cc: uri@… added
Last edited 10 years ago by mouse07410 (Mouse) (previous) (diff)

comment:5 Changed 10 years ago by mouse07410 (Mouse)

Running a wonderful program "dumpasn1", I found that indeed most algorithms are encoded with an explicit ASN.1 NULL for parameters, but the first occurrence is encoded with no parameters at all.

Therefore my workaround probably is a real patch for this issue.

P.S. Surprisingly, this issue is not triggered on the CA cert that exhibits the same disparity in signature algorithm parameters encoding.

Changed 10 years ago by mouse07410 (Mouse)

Attachment: RabbitMQ_Test_CA.dump.txt added

Dump of ASN.1 encoding of a cert, illustrating problem: look at data at offset 20, and compare it with offsets 223 and 628.

comment:6 Changed 10 years ago by neverpanic (Clemens Lang)

Cc: cal@… removed

As the reporter you are automatically Cc'd, so you don't need to Cc yourself.

This isn't a problem with MacPorts' build of OpenSSL, but OpenSSL itself. It is being tracked by the OpenSSL developers in http://rt.openssl.org/Ticket/Display.html?id=3665&user=guest&pass=guest. I don't feel comfortable applying a patch that changes certificate verification without analysis and approval of the OpenSSL developers.

We will patch this when upstream commits or releases a new version with a fix.

comment:7 Changed 10 years ago by neverpanic (Clemens Lang)

Cc: cal@… added; uri@… removed

comment:8 Changed 10 years ago by mouse07410 (Mouse)

Yeah, that's fair.

In the meanwhile, is there a way for me to package my patch in such a way that my Macports would pick it and apply to my build, while we all are waiting for the OpenSSL developers to weigh in? Because regardless of what & when they decide, I need this patch for as long as I'm using Mac OS X. (And I've dealt enough with cryptography to know that my patch is safe, so my computers will run it, even if others won't.)

comment:9 Changed 10 years ago by neverpanic (Clemens Lang)

Sure, you can put the file in $(port dir openssl)/files and add its filename to the patchfiles directive (creating it if it doesn't exist) in $(port file openssl). Then, re-install openssl using sudo port -fsn upgrade openssl.

Last edited 10 years ago by neverpanic (Clemens Lang) (previous) (diff)

comment:10 Changed 10 years ago by mouse07410 (Mouse)

Thank you! Did the steps you mentioned, and got openssl-1.0.1k re-installed with my patch. A few things:

  • Since I have GMP port installed, I decided to add GMP dependency to my openssl. So I added "port:gmp" to "depends_lib". However the build did not seem to pick the gmp library ("port upgrade" would fail) until I explicitly added "-lgmp" to "configure.args". That sounds wrong?
  • The exact command that worked for me was sudo port -n upgrade -s --force openssl, and after that it had problems activating openssl (my fault, I think), so I had to activate it by force sudo port -f activate openssl. After that everything seemed fine.

In the meanwhile, OpenSSL developers are discussing the best course of action. :-)

comment:11 in reply to:  10 Changed 10 years ago by neverpanic (Clemens Lang)

Replying to uri@…:

Since I have GMP port installed, I decided to add GMP dependency to my openssl. So I added "port:gmp" to "depends_lib". However the build did not seem to pick the gmp library ("port upgrade" would fail) until I explicitly added "-lgmp" to "configure.args". That sounds wrong?

No, that sounds exactly right. If adding the dependency was all it took to make openssl link against gmp, all users who built from source and have gmp installed would end up with openssl linked against it, but the dependency relation was not necessary picked up by MacPorts. This would lead to incorrect dependency information, breakage when later uninstalling gmp and non-reproducible builds (because they depend on your selection of ports), which we try to avoid at all cost.

comment:12 Changed 10 years ago by mouse07410 (Mouse)

I've modified openssl Portfile to add more variants (gmp, JPAKE, etc).

Would it be possible to incorporate those additions into the mainstream? I'd love it.

Thanks!

comment:13 Changed 10 years ago by mouse07410 (Mouse)

Also, a strange (for me :) thing: after that successful upgrade of openssl (in a few hours), I did

sudo port selfupdate; sudo port upgrade outdated

which also succeeded. But when I looked at "$(port file openssl)" I see that it reverted to the original version! And my patch file that I put in "$(port dir openssl)" is also gone. Did I do something wrong? Is there a way to preserve my modification to Portfile, and my additions to "$(port dir openssl)"?

P.S. I still hope you'd accept my enhanced Portfile with variants. ;)

Changed 10 years ago by mouse07410 (Mouse)

Attachment: patch-null-absent.diff added

Updated patch for signature algorithm mismatch and ASN.1 type comparison bug.

comment:14 Changed 10 years ago by mouse07410 (Mouse)

Oh, and based upon discussion here http://rt.openssl.org/Ticket/Display.html?id=3665#txn-50911 I've changed the patch. Steve Henson correctly pointed out that to change ASN1_TYPE_cmp() may not be appropriate, as there could be cases when null pointer (absent list) means something different from list being NULL.

To address that comment, I've made sure the workaround applies only to the case when two algorithms are compared, based on RFC 5754 and 5280 that state that AlgorithmIdentifier parameter list can be absent or represented as ASN.1 NULL - and implementations MUST accept both cases.

So please find attached my updated patch "patch-null-absent.diff". I'm also posting it upstream.

Thanks!

comment:15 Changed 10 years ago by neverpanic (Clemens Lang)

If you are using rsync to sync your ports tree (which is the default) your changes will be reverted on selfupdate. Workarounds are

Whether we should add more variants to openssl is essentially the maintainer's decision, but I wouldn't be opposed to it unless these variants somehow break API or ABI.

As with your previous patch, I'm hesitant to pull it into MacPorts' OpenSSL without upstream approval.

comment:16 in reply to:  15 ; Changed 10 years ago by mouse07410 (Mouse)

Replying to cal@…:

If you are using rsync to sync your ports tree (which is the default) your changes will be reverted on selfupdate.

:-) I was certain that I was doing it to myself!

Workarounds are

I thought that the best way is to add a local port tree, as shown in the URL you kindly provided.

This is what I've created:

$ ls -FR ~/ports
PortIndex		PortIndex.quick		devel/

/Users/ur20980/ports/devel:
openssl/

/Users/ur20980/ports/devel/openssl:
Portfile	files/

/Users/ur20980/ports/devel/openssl/files:
patch-null-absent.diff

I've created index with "portindex", like the Web page told. However when I try to do "sudo port selfupdate", I'm getting this:

$ sudo port selfupdate
Password:
--->  Updating MacPorts base sources using rsync
MacPorts base version 2.3.3 installed,
MacPorts base version 2.3.3 downloaded.
--->  Updating the ports tree
Error: updating PortIndex for file://Users/ur20980/ports failed
--->  MacPorts base is already the latest version

The ports tree has been updated. To upgrade your installed ports, you should run
  port upgrade outdated

Whether we should add more variants to openssl is essentially the maintainer's decision, but I wouldn't be opposed to it unless these variants somehow break API or ABI.

I'm pretty sure they don't break anything, because they just apply certain OpenSSL configuration options (and they don't seem to interfere with anything on my machine :).

Perhaps you could point me at a person that I should ask about this? Is it mww@…?

As with your previous patch, I'm hesitant to pull it into MacPorts' OpenSSL without upstream approval.

Yes, I understand and appreciate your position.

But they surely do take their time, especially considering the obviousness of the issue (there was also a bug in ASN.1 type comparison function - a one-liner that I fixed along the way :).

comment:17 in reply to:  16 Changed 10 years ago by larryv (Lawrence Velázquez)

This ticket has gone almost completely off-topic. Please use macports-dev to continue discussing local ports trees or new openssl variants (which I am opposed to adding, without more convincing reasons).

comment:18 Changed 10 years ago by neverpanic (Clemens Lang)

Replying to uri@…:

I've created index with "portindex", like the Web page told. However when I try to do "sudo port selfupdate", I'm getting this:

$ sudo port selfupdate
Password:
--->  Updating MacPorts base sources using rsync
MacPorts base version 2.3.3 installed,
MacPorts base version 2.3.3 downloaded.
--->  Updating the ports tree
Error: updating PortIndex for file://Users/ur20980/ports failed
--->  MacPorts base is already the latest version

The ports tree has been updated. To upgrade your installed ports, you should run
  port upgrade outdated

Edit your sources.conf and add [nosync] to the line adding your local repository. If it is also marked as [default] separate the options using a comma: [default,nosync].

Perhaps you could point me at a person that I should ask about this? Is it mww@…?

Yes. He should already get an email for each comment in this ticket, but he hasn't been very active recently, which is why I've taken care of all pressing issues with openssl in the last few months. Nevertheless, go ahead and email him, or open a new ticket with a patch and assign it to him/put him on cc.

But they surely do take their time, especially considering the obviousness of the issue (there was also a bug in ASN.1 type comparison function - a one-liner that I fixed along the way :).

Yeah, I know. Nonetheless, I'd like to avoid patching security-relevant stuff, even if the issue is obvious. We're trying to avoid replicating some of the disasters Debian created when patching OpenSSL ;-)

comment:19 in reply to:  18 ; Changed 10 years ago by mouse07410 (Mouse)

Replying to cal@…:

Error: updating PortIndex for file://Users/ur20980/ports failed

Edit your sources.conf and add [nosync] to the line adding your local repository. If it is also marked as [default] separate the options using a comma: [default,nosync].

Thank you - adding [nosync] and a missing 3rd slash fixed the day!

Perhaps you could point me at a person that I should ask about this? Is it mww@…?

Yes. He should already get an email for each comment in this ticket, but he hasn't been very active recently, which is why I've taken care of all pressing issues with openssl in the last few months. Nevertheless, go ahead and email him, or open a new ticket with a patch and assign it to him/put him on cc.

Great! I'm polishing the Portfile now. Hitting a strange obstacle:

--->  Updating database of binaries
--->  Scanning binaries for linking errors
--->  Found 62 broken file(s), matching files to ports   
--->  Found 3 broken port(s), determining rebuild order
--->  Rebuilding in order
     openssl @1.0.1k +universal
     curl @7.40.0 +ssl+universal
     gnome-vfs @2.24.4 +universal
--->  Computing dependencies for openssl
--->  Cleaning openssl
--->  Computing dependencies for curl
--->  Cleaning curl
--->  Computing dependencies for gnome-vfs
--->  Cleaning gnome-vfs
--->  Scanning binaries for linking errors
--->  Found 62 broken file(s), matching files to ports
--->  Found 3 broken port(s), determining rebuild order
--->  Rebuilding in order
     openssl @1.0.1k +universal
     curl @7.40.0 +ssl+universal
     gnome-vfs @2.24.4 +universal
--->  Computing dependencies for openssl
--->  Fetching distfiles for openssl
--->  Attempting to fetch patch-Makefile.org.diff from http://ykf.ca.distfiles.macports.org/MacPorts/mpdistfiles/openssl
--->  Attempting to fetch patch-Makefile.org.diff from http://distfiles.macports.org/openssl
--->  Attempting to fetch patch-Makefile.org.diff from http://mse.uk.distfiles.macports.org/sites/distfiles.macports.org/openssl
--->  Attempting to fetch patch-Makefile.org.diff from http://nue.de.distfiles.macports.org/macports/distfiles/openssl
--->  Attempting to fetch patch-Makefile.org.diff from http://fco.it.distfiles.macports.org/mirrors/macports-distfiles/openssl
--->  Attempting to fetch patch-Makefile.org.diff from http://sea.us.distfiles.macports.org/macports/distfiles/openssl
--->  Attempting to fetch patch-Makefile.org.diff from http://lil.fr.distfiles.macports.org/openssl
--->  Attempting to fetch patch-Makefile.org.diff from http://www.openssl.org/source/
--->  Attempting to fetch patch-Makefile.org.diff from http://her.gr.distfiles.macports.org/mirrors/macports/mpdistfiles/openssl
--->  Attempting to fetch patch-Makefile.org.diff from http://cjj.kr.distfiles.macports.org/openssl
--->  Attempting to fetch patch-Makefile.org.diff from http://aarnet.au.distfiles.macports.org/pub/macports/mpdistfiles/openssl
--->  Attempting to fetch patch-Makefile.org.diff from http://jog.id.distfiles.macports.org/macports/mpdistfiles/openssl
--->  Attempting to fetch patch-Makefile.org.diff from http://svn.macports.org/repository/macports/distfiles/openssl
Error: org.macports.fetch for port openssl returned: fetch failed
Please see the log file for port openssl for details:
    /opt/local/var/macports/logs/_Users_uri_ports_devel_openssl/openssl/main.log
Error: Unable to upgrade port: 1
Error rebuilding openssl
    while executing
"error "Error rebuilding $portname""
    (procedure "revupgrade_scanandrebuild" line 395)
    invoked from within
"revupgrade_scanandrebuild broken_port_counts $opts"
    (procedure "macports::revupgrade" line 5)
    invoked from within
"macports::revupgrade $opts"
    (procedure "action_revupgrade" line 2)
    invoked from within
"action_revupgrade $action $portlist $opts"
    (procedure "action_upgrade" line 25)
    invoked from within
"$action_proc $action $portlist [array get global_options]"
    (procedure "process_cmd" line 103)
    invoked from within
"process_cmd $remaining_args"
    invoked from within
"if { [llength $remaining_args] > 0 } {

    # If there are remaining arguments, process those as a command
    set exit_status [process_cmd $remaining..."
    (file "/opt/local/bin/port" line 5268)
$ sudo port upgrade outdated
Nothing to upgrade.

It looks like "port" cannot fetch openssl patch files? I did not copy to my local ports directory anything, except for my (modified) Portile, and my additional patch:

$ ls -RF ~/ports
PortIndex		PortIndex.quick		devel/

/Users/uri/ports/devel:
openssl/

/Users/uri/ports/devel/openssl:
Portfile	files/

/Users/uri/ports/devel/openssl/files:
patch-null-absent.diff
$ 

Am I doing something wrong???

But they surely do take their time, especially considering the obviousness of the issue (there was also a bug in ASN.1 type comparison function - a one-liner that I fixed along the way :).

Yeah, I know. Nonetheless, I'd like to avoid patching security-relevant stuff, even if the issue is obvious. We're trying to avoid replicating some of the disasters Debian created when patching OpenSSL ;-)

:-) :-) I'm with you here. Wouldn't want my name associated with such a "sensation" either. :-)

comment:20 in reply to:  19 ; Changed 10 years ago by neverpanic (Clemens Lang)

Replying to uri@…:

Great! I'm polishing the Portfile now. Hitting a strange obstacle:

Please open a new ticket about this and discuss it there.

I did not copy to my local ports directory anything, except for my (modified) Portile, and my additional patch:

You need to copy the original files/ directory as well.

comment:21 in reply to:  20 Changed 10 years ago by mouse07410 (Mouse)

Replying to cal@…:

Replying to uri@…:

Great! I'm polishing the Portfile now. Hitting a strange obstacle:

Please open a new ticket about this and discuss it there.

As a matter of fact, unnecessary - your answer below solved it.

I did not copy to my local ports directory anything, except for my (modified) Portile, and my additional patch:

You need to copy the original files/ directory as well.

I will be opening a new ticket with Portfile patch/update. I guess I'll label it as feature request?

comment:22 Changed 10 years ago by jmroot (Joshua Root)

Owner: changed from mww@… to larryv@…

comment:23 Changed 8 years ago by neverpanic (Clemens Lang)

Resolution: wontfix
Status: newclosed

Upstream rejected the patch, so we aren't going to carry it against their decision.

Note: See TracTickets for help on using tickets.