Closed Bug 1523130 Opened 7 years ago Closed 7 years ago

(Re-)enable support for self-signed X.509 S/MIME end entity certificates by disabling PKI checks for email certificates

Categories

(MailNews Core :: Security: S/MIME, defect)

defect
Not set
major

Tracking

(Not tracked)

RESOLVED WONTFIX

People

(Reporter: it, Unassigned)

Details

Attachments

(2 files)

User Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:64.0) Gecko/20100101 Firefox/64.0

Steps to reproduce:

Since mid-2014, self-signed S/MIME certificates unfortunately cannot be used any more.
This happened for unclear reasons somewhere between Thunderbird versions 30 and 31,
By then, it had been possible to import/use/accept such X.509 certificates for email addresses of oneself and others.
Interestingly, this feature is still documented on pages like http://kb.mozillazine.org/Installing_an_SMIME_certificate

The inability to use self-signed (or self-issued, to be more precise) S/MIME certs is a major regression.
It makes convenient and wide-spread use of encryption for email exchange nearly impossible without a proper PKI.

The vast majority of email users cannot or do not want to obtain personal certificates from a widely accepted CA service, for instance because this requires trusting such CAs, requesting certificates is a non-trivial process and typically costs money, and enrolling email certs with a public CA may result in email addresses being harvested for spamming.
While PGP offers conceptually better support for self-signed certs via the Web Of Trust, it is less convenient to use than S/MIME for other reasons - in particular, major email clients do not support PGP without extensions.

The way Thunderbird used to support self-signed X.509 certs was pretty weird: they had to bear CA attributes and consequently needed to be imported into the "Authorities" list of certs and trusted like a CA, which made them rather dangerous to use. So when considering ways to re-enable the use of self-signed S/MIME certs I figured this is not the way to go for the reasons given.

Here is a straightforward different approach for a clean way of supporting and using self-signed S/MIME certs: do not mark them as CA, such that they can only be used as end-entity certs. Although being self-signed, allow their use as soon as they have been imported as own credentials (under "Your Certificates") or other people's certs (under "People"), respectively.

The attached patch provides a proof-of-concept implementation of this proposal. Given the not very well-structured Mozilla security software it was pretty hard for me to find out how to do this in an effective, simple, and security-preserving way, but meanwhile I think I've got pretty close to that. So I would like to share this with reviewers/developers here for discussion and potential improvements.

What is still missing here for wide-spread usability of self-signed S/MIME certs is a feature to generate them in a user-friendly way, without the need to resort to external (and typically rather awkward to use) tools, as reported and motivated already in bug 323343.

Severity: normal → major
Component: Security → Libraries
OS: Unspecified → All
Product: Thunderbird → NSS
Hardware: Unspecified → All
Version: 31 Branch → other

I second the proposition that using self-signed S/MIME certificates should be possible and should be made easy! I have spent much time trying to persuade other to encrypt with S/MIME, and it mainly failed because users did not manage to install CA certificates properly. It would be best, as this proposal suggests, if recipients just had to import self-signed certificates under people and set their trust.

I meanwhile noticed that a request that Mozilla Thunderbird should directly support the generation of self-signed email certs was issued (in bug 202329) already nearly 16 years ago!

I found yesterday that the patch I uploaded initially was incomplete.
Here is the full version enabling all intended use cases (including email signature with self-issued end entity certs).

Kai, can you take charge of triaging this?

Flags: needinfo?(kaie)
QA Contact: jjones
Component: Libraries → Security: S/MIME
Flags: needinfo?(kaie)
Product: NSS → MailNews Core
QA Contact: jjones
Version: other → unspecified

Your patch suggests to disable the PKI checks for email certificates. We cannot do that.

If you want to use certificates that you create yourself, the correct way is to create two certificates:

  • your own root CA
  • use your own root CA to issue an email certificate
  • import your own root CA as trusted for email
  • import your email certificate, too

That doesn't require any changes to the code.

If everyone in your group does the above, then you'll have to import two certicates for each contact: the contact's root CA certificate, and the contact's email certificate.

Each friend could add a name constraints extension to their CA, which limits the certificates trusted by that CA to the single email of the contact who created the CA. That way, importing your contact's CA wouldn't result in any broader trust beyond the contact's email address.

Another alternative, if you decide to trust the cacert.org community for verifying email addresses, each person in your group could get a free email certificate from them, and you'd have to trust the root CA from cacert.org for issueing email certificates.

I will show you example commands that can be used to achieve the above.
You require the "certutil" utility, which is available on Linux distributions.

Lines below start with $ show commands that you must enter in a terminal.
Other lines may show output that is printed on screen, mixed with input you must provide.

Replace the placeholders with your own name and email addresses.

$ mkdir $HOME/my-ca-dir
$ cd $HOME/my-ca-dir
$ certutil -d . -N --empty-password

$ certutil -d . -S -n my-ca -s "CN=Insert-Your-Name-Here personal email CA" -x -t ,C, -m 0 -v 120 -1 -2 --extNC

Generating key. This may take a few moments...

	0 - Digital Signature
	1 - Non-repudiation
	2 - Key encipherment
	3 - Data encipherment
	4 - Key agreement
	5 - Cert signing key
	6 - CRL signing key
	Other to finish

0
0 - Digital Signature
1 - Non-repudiation
2 - Key encipherment
3 - Data encipherment
4 - Key agreement
5 - Cert signing key
6 - CRL signing key
Other to finish
5
0 - Digital Signature
1 - Non-repudiation
2 - Key encipherment
3 - Data encipherment
4 - Key agreement
5 - Cert signing key
6 - CRL signing key
Other to finish
9
Is this a critical extension [y/N]?
y
Is this a CA certificate [y/N]?
y
Enter the path length constraint, enter to skip [<0 for unlimited path]: >
Is this a critical extension [y/N]?
y

Select one of the following general name type:
2 - rfc822Name
3 - dnsName
5 - directoryName
7 - uniformResourceidentifier
8 - ipAddress
9 - registerID
Any other number to finish
Choice: > 2

Enter data:
insert-your-email-address-here@domain.com
Type of Name Constraint?
1 - permitted
2 - excluded
Anyother number to finish
Choice > 1
Add another entry to the Name Constraint Extension [y/N]
n
Is this a critical extension [y/N]?
n

$ certutil -d . -S -n your-name-date-YYYYMMDD -s "E=insert-your-email-address-here@domain.com, CN=Your Name" -c my-ca -t ,, -m 1 -v 24 -1 -2 -6 -7 insert-your-email-address-here@domain.com

Generating key. This may take a few moments...

	0 - Digital Signature
	1 - Non-repudiation
	2 - Key encipherment
	3 - Data encipherment
	4 - Key agreement
	5 - Cert signing key
	6 - CRL signing key
	Other to finish

0
0 - Digital Signature
1 - Non-repudiation
2 - Key encipherment
3 - Data encipherment
4 - Key agreement
5 - Cert signing key
6 - CRL signing key
Other to finish
2
0 - Digital Signature
1 - Non-repudiation
2 - Key encipherment
3 - Data encipherment
4 - Key agreement
5 - Cert signing key
6 - CRL signing key
Other to finish
9
Is this a critical extension [y/N]?
y
0 - Server Auth
1 - Client Auth
2 - Code Signing
3 - Email Protection
4 - Timestamp
5 - OCSP Responder
6 - Step-up
7 - Microsoft Trust List Signing
Other to finish
3
0 - Server Auth
1 - Client Auth
2 - Code Signing
3 - Email Protection
4 - Timestamp
5 - OCSP Responder
6 - Step-up
7 - Microsoft Trust List Signing
Other to finish
9
Is this a critical extension [y/N]?
n
Is this a CA certificate [y/N]?
n
Enter the path length constraint, enter to skip [<0 for unlimited path]: >
Is this a critical extension [y/N]?
y

$ certutil -d . -L -n my-ca -a > Insert-Your-Name-Here-ca.pem

Optional to display you CA's fingerprint:

$ pp -t c -a -i Insert-Your-Name-Here-ca.pem |grep -A1 -i fingerprint
Fingerprint (SHA-256):
E9:08:86:F1:A6:6D:86:0C:9E:A4:6F:6D:1C:A5:46:0D:B9:E2:22:2C:24:9B:27:4C:30:C1:83:78:F3:9C:B3:8D
Fingerprint (SHA1):
55:5E:31:73:69:70:2F:F1:CC:9C:ED:76:39:7F:95:DC:17:94:A1:C5

(if your distribution doesn't provide the NSS pp utility, you can use openssl:
$ openssl x509 -in Insert-Your-Name-Here-ca.pem -noout -fingerprint -sha1
$ openssl x509 -in Insert-Your-Name-Here-ca.pem -noout -fingerprint -sha256
)

$ pk12util -d . -o your-name-date-YYYYMMDD.p12 -n your-name-date-YYYYMMDD
(enter a password, or press enter twice for none)

Open Thunderbird, preferences, advanced, certificate manager.
Authorities tab.
Import Insert-Your-Name-Here-ca.pem
Check email ca

your certificates tab
import your-name-date-YYYYMMDD.p12
(enter the password you used above for pk12util)

Marking wontfix.

The correct approach, which is equivalent to using a self-signed certificate, is to use a self-signed CA, trust that CA, and use that CA to issue your certificates.

Status: UNCONFIRMED → RESOLVED
Closed: 7 years ago
Resolution: --- → WONTFIX

Kai, your 3 comments (#6-8) including the instructions for certutil (thanks!) very much confirm Daniel's initial bug report. However, at least from my point of view, you haven't yet commented on Daniel's major point:

What is still missing here for wide-spread usability of self-signed S/MIME certs is a feature to generate them in a user-friendly way, without the need to resort to external (and typically rather awkward to use) tools, as reported and motivated already in bug 323343.

There are perhaps good reasons why this is not going to happen. But it would be good (and fair) to have your opinion on this.

Clarifying the subject. The wontfix was for the suggested approach, which would disable the checking for PKI inherited trust for all email certificates.

Summary: (Re-)enable support for self-signed X.509 S/MIME end entity certificates → (Re-)enable support for self-signed X.509 S/MIME end entity certificates by disabling PKI checks for email certificates

Thanks Kai Engert for having a look at this patch. Yet your feedback on it is unfortunately rather vague.

Which of the three preliminary changes I suggested is/are too drastic in your view and why specifically?
As I wrote, I'd welcome technical discussion and concrete hints for improvements.

Please note that the changes I gave aim at allowing self-issued certificates

  • only for the specific purpose of signing messages and sending encrypted messages, and
  • only for certs that have been explicitly set as the own credentials or added as certs of other people.

In contrast, the former (until mid 2014) solution was really dangerous because it required that for self-signed email user certs

  • their CA flag had to be true, which was very misleading and confusing, and
  • these certs had to be trusted as issuer of other certs, with the potential to undermine all PKI-based security.

Thanks also for the detailed alternative approach you gave. Conceptually is is somewhat between the two approaches I just summarized. It has various rather severe issues, on which I'll comment soon.

To sum up, I do not (yet) see your point that any critical PKI checks for such self-issued certs are disabled.
Could you please expand on that?

@Kai Engert, here is my feedback on the alternative approach you described above.

Certutil is somewhat less arcane than, e.g., the well-known openssl CLI, but using it is still awkward. So it's certainly nice and helpful that you gave a concrete Micro-HOWTO to illustrate the practicality of your approach.

For the creation of the key store you suggested using the --empty-password option without any word of warning.
For productive (non-example) use this is a pretty bad idea since the secret keys are stored in a file without any protection, such that anyone who has (or gains) access to the machine can copy and abuse them!

It would have been good to mention that

  • with the -v option the validity period is given in number of months, and that
  • using the -7 option a whole comma-separated list of email addresses (and thus multiple SAN entries) can be given.

The example basic key usage you gave for the email user (end-entity) cert does not include Digital Signature, such that it cannot be used for email signature (checking).

In the basic constraints of the email CA cert you did not specify the path length constraint, thus you allow any number of sub-CAs, arbitrarily nested. Yet for the given use case the length should better be limited to 0, such that the email CA is restricted to issue only end-entity certs.

You mentioned above:

Each friend could add a name constraints extension to their CA, which limits the certificates trusted by that CA to the single email of the contact who created the CA. That way, importing your contact's CA wouldn't result in any broader trust beyond the contact's email address.

At first sight this appears to be viable way of making your approach more secure than the hazardous approach using self-signed certs that was possible with Thunderbird by mid-2014, where, as I wrote above:

these certs had to be trusted as issuer of other certs, with the potential to undermine all PKI-based security.

Yet I find it strange that although you are aware of this severe CA misuse problem you mention this just as an option and do not strongly recommend it.

Moreover, even if users care to follow it, this adds virtually no security, for several reasons:

  • In your example you did not mark the name constraint extension as critical.
    This violates RFC 5280 (https://tools.ietf.org/html/rfc5280#section-4.2.1.9), which clearly says: "Conforming CAs MUST mark this extension as critical".
    The omission of the critical flag entitles any client software that does not understand/support this (uncommon) type of extension to simply ignore it when verifying certs!

  • It is rather uncertain that cert verification software diligently imposes the restrictions implied by these - rather unknown and complicated - X.509 name constraints. Note that many implementations of X.509 verification simply ignore all types of policy constraints or have obscure but potentially severe bugs.

  • Even if rfc822Name constraints (limiting the set of email addresses for which the CA may issue certs) are given and are respected,
    they do not at all constrain the use of the CA for issuing certs with other types of names (such as DNS names, IP addresses, and directory names)!
    In particular, each such "email CA" may still be abused by its owner to produce fake certs for any (TLS) servers, such as web servers and email servers.

To sum up:

  • Your alternative approach, though it may look pretty secure to inexperienced users (and likely even to people with basic understanding of IT security), is conceptually and practically flawed in many respects, and thus is nearly as hazardous as the weird approach supported by Thunderbird until mid-2014.
  • Even if it was secure, it would be rather painful to use because every party would need to manage two certs for itself and for each partner following the same approach.
    Since most email users already have difficulties sufficiently understanding and managing the use of one cert per party, I do not think that it is realistic that they will be willing and able to cope with two certs (even of different type) per party.

In contrast, the approach I sketched is conceptually and practically much simpler, cleaner, and way more secure.
Using just one cert per party that is self-signed (or at least self-issued) and that is just an entity cert (i.e., does not have CA trust and capabilities) does not suffer from any of the issues I've just mentioned here.

(In reply to David von Oheimb from comment #11)

Which of the three preliminary changes I suggested is/are too drastic in your view and why specifically?

They all seem to be part of the same strategy. You enable trust for a certificate, based on its properties as email certificates, by skipping the regular checks for a chain of trust to a trusted root CA certificate.

As I wrote, I'd welcome technical discussion and concrete hints for improvements.

Your suggested implementation breaks the regular expectations of how S/MIME certificates are verified.

Please note that the changes I gave aim at allowing self-issued certificates

  • only for the specific purpose of signing messages and sending encrypted messages, and
  • only for certs that have been explicitly set as the own credentials or added as certs of other people.

But you implemented it in a way that breaks the existing functionality. Simply importing a certificate shouldn't be equivalent to trusting a certificate. For example, with PKI you can have intermediate CA certificates available with a neutral trust setting. Such intermediates can help the software to discover a chain of trust to a trusted issuer root CA, but if none can be found, no trust is implied by the availability of the intermediate.

The NSS library and database has the ability to set explicit trust for end entity certificates. So in addition to importing another person's certificate you'd have to explicitly mark it as trusted.

Thunderbird today doesn't offer a user interface for marking other people's certificates as explicitly trusted. It wasn't part of the feature design. In theory, Thunderbird's user interface could get enhanced to allow editing the explicit trust setting for another person's certificate. (Trust in this context means, that the ownership of the private key associated to the certificate was confirmed to belong to the person controlling the email address in the certificfate.)

To sum up, I do not (yet) see your point that any critical PKI checks for such self-issued certs are disabled.

I might be misunderstanding your comment, but are you claiming that your patch doesn't disable checks?

Regarding comment 12:

David, I see support for self-signed S/MIME certificates as an advanced scenario that requires a good understanding of email security and the keys and trust settings that are related to it. The current Thunderbird S/MIME implementation targets users who might not have that level of understanding. Potentially Thunderbird could be enhanced to support self-signed certificates, but it would require a set of modifications in the user interface to ensure that users don't accidentally trust other's certificates, and don't lose the protections they might be assuming.

Because you mentioned self signed certificates, and using low level tools, you have demonstrated that you're beyond the skills of average users, and gave me the impression that you're seeking a solution for expert users. Based on that I had tried to help you, by giving you examples how expert users could potentially get what you want without being required to modify Thunderbird. Your comment 12 mentions some helpful details, and it shows you have learned that managing certificates is complex and requires care, that's good. I think you shouldn't have assumed my comments to be a perfect turnkey solution, bugzilla is a platform for developing technical solutions, and that process usually requires several iterations, with peer review and feedback on ideas. I'm not surprised that you were able to find improvements to my initial suggestion.

An approach that uses self-signed CAs would clearly target expert users, and I wouldn't recommend it for most users. However, in order to make it technically work for expert users, no modifications are required for the existing Thunderbird code, and that was my point in given you the example.

You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: