Open Bug 1581796 Opened 5 years ago Updated 7 months ago

Add UI to Thunderbird for creating a key pair and an S/MIME certificate request (CSR)

Categories

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

enhancement

Tracking

(Not tracked)

People

(Reporter: KaiE, Assigned: KaiE)

References

Details

(Whiteboard: project-tracker)

Attachments

(15 files)

Support for the HTML keygen tag was recently removed from Firefox.

This makes it more difficult for users to create a Certificate Signing Request (CSR), where the private key resides on their local system.

I suggest that we implement a user interface mechanism, maybe by using a button in security account prefs, that could be used to create a CSR for the account's email address, and save it to a file. The user could then paste the CSR into a web form for requesting a certificate.

This assumes that Firefox/Mozilla will have support for key generation and APIs.

From bug 1315460 comment 47, we should do this using WebCrypto: https://www.w3.org/TR/WebCryptoAPI
There's an exportKey method, https://www.w3.org/TR/WebCryptoAPI/#dfn-SubtleCrypto-method-exportKey but other than that, I didn't look at how/if this can be used.

Anyway, I'd assume removal of <keygen> is the last blow to non-corporate usage of S/MIME certificates.

Severity: normal → S3

I think using webcrypto isn't the best approach.
We need the key in our internal NSS key store. There's no benefit in having it temporarily in the isolated webcrypto space.

We had old code that was removed from Firefox. I think it should be easy to bring that code back into Thunderbird. We could have a button in account settings, next to the s/mime certificate selection, that offers generating a CSR. It could then be made available for saving to a file.

I think this would be very little work to do, I'd like to look into it.

You can use some ideas from these scripts, the first generates RSA / NIST EC keys and csr, the second generates experimental EdDSA and ECDH (Ed25519,Ed448 and X25519,X448). I used CABForum SMIME SBr to get everything to come out correctly. When ECDSA (NIST) support is ready (bug#676118#c20), the first script will be just fine.

The package contains a script, result files and a dump of the ASN.1 structure.

Links:
https://github.com/cabforum/smime/blob/main/SBR.md#713-algorithm-object-identifiers

On the above page, they haven't posted OID for X25519 and X448 (encryption keys), script creates these keys.

X25519  OID 1.3.101.110 (id-X25519)
X448    OID 1.3.101.111 (id-X448)
Attached file RSA_NIST_csr.tar.gz
Attached file EDWARDS_csr.tar.gz
Whiteboard: project-tracker
Summary: Allow Thunderbird users to create a key pair and a certificate request (CSR) → Add UI to Thunderbird for creating a key pair and an S/MIME certificate request (CSR)

leszek.zablocki : The implementation for this bug should not use openssl and must not use shell scripting. It should use the NSS library code.

I have an initial patch, which was based on copying code from TB 68 and from NSS certutil. It calls the correct functions, but without following any cleanup or code style rules yet, and it simply replaces what one of our buttons in settings do (to allow me to quickly execute the code).

However, using this hack, I was able to log a CSR on the error console, and I was able to use other tools to process that request. I successfully used NSS certutil to process that CSR, generate a cert, import the cert back into Thunderbird, and it's then listed correctly in TB's cert manager.

I'm attaching the initial patch, and hope I will be able to clean it up in the near future.

This may be another way: https://gist.github.com/dmikey/4c6872211f53adf0b52de9c049f45495
Note that pkijs.js is already available (vendored) in mozilla code.

(In reply to Magnus Melin [:mkmelin] from comment #10)

This may be another way: https://gist.github.com/dmikey/4c6872211f53adf0b52de9c049f45495

How would we then store the secret key in the permanent NSS storage?
It seems easier to use the NSS code, because the secret key must be stored by NSS anyway.

I suggest to implement this in two steps.

In a first step, I want to introduce a minimal UI with minimal guidance.
In the account settings, end-to-end encryption, I want to show a brief information text, e.g.
To obtain an S/MIME certificate,
Thunderbird can create a Certificate Signing Request (CSR)
for submission to a Certificate Authority (CA).
Plus a button
[ Generate CSR... ]

If clicked, Thunderbird prompts for a filename.
If the user confirms, a CSR would be created with default parameters, and the CSR will be saved.

In a second step, it would be nice to introduce a small guidance dialog.
Instead of simply prompting for the filename, we could show a dialog like this:

Select the filename and folder to use for saving the CSR.
[ filename ]

Select the type of certificate
(*) RSA
( ) ECC

Thunderbird will create a random key for the Certificate Signing Request (CSR).
Thunderbird may be unresponsive for a few moments after the button is clicked.

When done, we could show a confirmation prompt, that allows the user to also view the CSR directly in a text view, because the user may often want to submit the text CSR into a web form in the browser.

(In reply to Kai Engert (:KaiE:) from comment #11)

How would we then store the secret key in the permanent NSS storage?

I assume we can call the same importing code the certificate manager has. Or Just have the user import it at the same time they import the certificate from the authority.

(In reply to Magnus Melin [:mkmelin] from comment #13)

(In reply to Kai Engert (:KaiE:) from comment #11)

How would we then store the secret key in the permanent NSS storage?

I assume we can call the same importing code the certificate manager has. Or Just have the user import it at the same time they import the certificate from the authority.

The problem is that you then need to pass around the private key. And NSS doesn't allow you to easily handle secret keys that are not yet connected to a certificate. The certificate doesn't have to handle this problem, because it only can import secret keys that are part of the certificate. It's really much easier to do everything in NSS.

I also have an idea for a simpler flow, that avoid having to introduce a new dialog, but reuse the prompt service instead. I'm on it and should have it done shortly.

The currently attached revision add these elements to the end-to-end encryption settings.

Attached image csr-algo-select.png

After clicking the button, the user will be prompt to select the file for saving, and in a second step, the user will be shown this selection prompt.
(The prompt is implemented by calling an existing, generic prompt dialog.)

Bob, FYI, you might be interested in this work. Because currently there is no convenient way for users to locally generate a new key pair for a CSR, I'd like to add this as a feature for Thunderbird.

I'd like to do this with the least amount of work, for an initial version, which is hardcoded to use the internal slot. (Doesn't offer token/smartcard selection.)

Also, because nowadays CAs seem to throw away most elements of CSRs anyway (besides the public key), I didn't bother with adding attributes/extensions to the CSR.

All I did was set the subject, and only this attribute:
MAIL=email-address@example.com

If you're interested to provide feedback, please see the attached patch. It reuses code from certutil and old Keygen code from PSM.

I'll attach two sample CSRs generated by this code, one RSA, one ECC.

Assignee: nobody → kaie

Actually, I wonder if I should rather use an empty subject.

A user might not pay close attention which account/identity is currently selected in account settings. They may end up submitting a CSR when requesting a cert for a different email address. If we include an email address, the user might accidentally submit a CSR containing an incorrect email address to a CA.

leszek.zablocki : The implementation for this bug should not use openssl and must not use shell scripting. It should use the NSS library code.

yea I know.

I wanted to help as much as I can, and I can only create simple scripts ;(

I can also keep a careful eye on someone's work, and so I'll throw in my three cents. I looked into how Kleopatra creates CSRs and one thing is thoughtful. She leaves 2 extensions: 1) X509v3 Subject Alternative Name and 2) X509v3 Key Usage. The latter extension does not matter (as you wrote CA strips extensions), but the former, SAN, appears instead of rfc822Mailbox (OID 0.9.2342.19200300.100.1.3) or emailAddress (OID 1.2.840.113549.1.9.1) in SubjectDN. This has its advantages: you can put several e-mail addresses and utf-8 addresses there. Besides, I read somewhere that it is generally considered to be an obsolete method to put an email address in SubjectDN. Everything is moving to SAN. You can write the function once and have peace of mind not to rework it later.

Regarding the fields in Subject DN. You can make custom fields (as in Kleopatra), or predefined (from SMIME BRs), or none. Kleopatra requires CN. I would COPY the tables from the SMIME BR and create a selectable list (custom/mailbox-validated/organization-validated/sponsor-validated/individual-validated profile). Mozilla created this specification, so it would be nice to find this feature in a flagship product.

Additionally, I would make sure that the fields in SubjectDN are UTF8String encoded, not PrintableString. Th. is, after all, multilingual.

You can also think about predefined csr signature algorithms.

             -- Signature Algorithm
RSA 2048 bit -- sha256
RSA 3072 bit -- sha384
RSA 4096 bit -- sha512
NIST P-256   -- ecdsa-with-SHA256
NIST P-384   -- ecdsa-with-SHA384
NIST P-521   -- ecdsa-with-SHA512

But that's pedantry, no?

tschüß!

Attached image kleopatra_x509.png
Attached file kleopatra_csr.txt
Attachment #9353471 - Attachment mime type: application/octet-stream → text/plain

Thanks Leszek for your feedback, your comments are good. The question is, is this additional work necessary? Do CAs depend on the attributes you're suggesting to add?

Initially I don't plan to offer a UI that could be used to specify that a request is specific to multiple email addresses.

I added the MAIL= to the DN because this was the most trivial thing for me to implement, and it can be used to identify/distinguish the request. If the CAs discard the attributes (including DN) anyway, it would be unnecessary to add those attributes.

It would be helpful to have feedback whether common CAs frequently make use of the attributes contained in the CSR.

If anyone would like to test the patch that I made so far, I've created experimental builds based on current TB Beta. (Don't use these builds with your regular settings from Thunderbird 115 stable, please use separate settings, a separate profile.)

Linux 64bit:
https://firefox-ci-tc.services.mozilla.com/api/queue/v1/task/c9P7GrI0Sw6RNda7cnPqFA/runs/0/artifacts/public/build/target.tar.bz2

Windows 64bit:
https://firefox-ci-tc.services.mozilla.com/api/queue/v1/task/VVn7cTBYS7-meQN_FuezbA/runs/0/artifacts/public/build/target.zip

Mac:
https://firefox-ci-tc.services.mozilla.com/api/queue/v1/task/JGkE5XNYTe20PqwKAF3ggw/runs/0/artifacts/public/build/target.dmg
(Not sure that works, might need security overrides to be able to get that to run.)

The question is, is this additional work necessary? Do CAs depend on the attributes you're suggesting to add?

I don't know. You would have to ask the major public CAs for their opinion. It also depends on the configuration of the programs (private CAs).

One more thing that came to my mind.

Scenario: user certificate expires. Before the expiration of 30 days, a message appears: "create CSR". There will be a jump to the CSR creation window. For example, a button is available, "construct a CSR based on a certificate." I'm assuming we don't want an email address in SubjectDN. Th. copies the SubjectDN and ONLY SAN extension from the existing certificate and fills in the blanks in the CSR creation window. If the SubjectDN field is rfc822Mailbox/emailAddress then Th. moves it to SAN. Finally, Th. eliminates duplicate addresses from this extension. Before that, you need to clear the fields and convert to UTF8 (UTF8String), for example (.sh):

printf '%s' "ONE_SUBJECTDN_FIELD_FROM_CRT" | LC_ALL=POSIX tr -d '[:cntrl:]' | iconv -cs -f ... -t UTF-8 | cut -c1-64)

In openssl version at least 3, there is an option to make CSR based on the certificate (copies SubjectDN + only SAN ext.):

$ openssl x509 -x509toreq -copy_extensions copyall -ext subjectAltName -in CERTIFICATE.crt -signkey NEW_GENERATED_KEY.pem -out OUT.csr

One more thing about the created CSR from your patch. I use guiDumpASN-ng to capture different things (Options -> Long Format). I think the program is also available in a console version (Peter Gutmann's stuff).

OBJECT IDENTIFIER rfc822Mailbox (0 9 2342 19200300 100 1 3)
(Some oddball X.500 attribute collection)

SMIME BRs compatible:

OBJECT IDENTIFIER emailAddress (1 2 840 113549 1 9 1)
(PKCS #9. Deprecated, use an altName extension instead)

ok, I did a little research. now it's not up to me what happens next ;) I think it's the right way to do "CSR creation UI". Sure, it's not 100% polished, but other things can be improved this way. The work may be triple or quadruple, but it's worth it. Plus, it complies with the standards (that's what they're for, right?).

I found the best user interface in the program "DigiCertUtil.exe", which creates CSRs. Even someone has created cool script based on this application. Check the CSR_UI_draft.htm file. I am not an htm specialist or UI engineer. It would be useful to have a flexbox wizard, etc. as well as restrictions on entering the maximum number of characters in the inputs. Details. Now they make such wizards assuming that the user is like a finite idiot, here: not too many options, not too few. Besides, we are making a CRYPTOGRAPHIC KEY, not supplies for the winter.

I went through the "SMIME BRs" specification and compiled all the SubjectDN fields. subjectDN_OID.txt file. Someone would have to check all these things after me. Also, based on the links in this file, I was looking for other "emailAddresses", exotic fields (in SubjectDN) that Th. could recognize and transfer to SAN. The other fields Th. must recognize. For verification, I used: openssl, guiDumpASN-ng, and Windows certutil.exe.

I wrote a script (yes, in bash!) that creates an EE certificate with these fields so that the functions can be verified. subjectDN_test.sh file. When creating certificates, most fields are "UTF8STRING" (string_mask = utf8only), but beware of other encodings (IA5STRING, PRINTABLESTRING). I assume that openssl creates these fields well. Check the subjectDN_test_EE.crt file. Note that if any fields appear twice, Windows counts the one that appeared later as more important.

Another advantage of SAN addresses is the new "smtpUTF8Mailbox" field (OID 1.3.6.1.5.5.7.8.9), designed specifically for addresses in UTF-8. Detection of such a field in SubjectDN would have to be handled differently. see bug#917869. In SAN they go into "otherName of type id-on-SmtpUTF8Mailbox."

If Th. were to read fields from an existing certificate (bug#1840860, bug#316062, bug#410548, bug#1745487) and fill in the gaps in the CSR window, SAN ext. would have to support anyway. Th. can copy only those SubjectDN fields it knows (i.e. those from "SMIME BRs"/ETSI + subset of ITU-T X.520) and ignore the rest. Same with SAN extension: accept only emails, ignore DNS, URI, IP etc.

Alternatively, you could think about combining the S/MIME and OpenPGP key wizard into one, etc. etc. (btw. is it possible to add OID fields in OpenpGP?) In the file "CSR_UI_draft.htm" there is a fieldset "Information", some information is identical for the creation of both types of keys, and SOMEONE needs to write this information, if my idea seems okay. And then someone has to translate that information, bug#1836855...

Another thing that might come in handy (someday) is scanning the certificate and sending information from it to the address book (oldschool Windows Live Mail).

It's better to do something once and properly than to make adjustments every now and then.

Attached file CSR_UI_draft.htm
Attached file subjectDN_OID.txt
Attached file subjectDN_test.sh
Attached file subjectDN_test_EE.crt

Implementing this feature is a bit more complicated than I thought. I have looked through the bugs in the NSS and will list the ones that tie in with my previous comments.


bug#211655, bug#207711, bug#220427, bug#237077, bug#355096, bug#360425, bug#392478, bug#426872, bug#561689, bug#54969, bug#232775, bug#1757758


I tested most of the new fields from the SMIME BRs specification and created test certificates. This number of fields is sufficient in my opinion. From the previous script, I corrected LEI+LEIrole; Subject Directory Attributes has the correct encoding and structure (I compared with the certificate from rfc). I got hooked on qualified certificates (ETSI, rfc) and created some for Napoleon Bonaparte. I suppose it complies with EU regulations (that's crazy). So, Kai, you have most of the fields in the x.509 S/MIME certificate and you can tweak something from that. I attach the script in the attachment. Additionally, it now uses dumpasn1 to know exactly what is being created. I also tested the fields in Windows "certutil.exe".

Maybe this package will be useful in closing this bug: bug#277797

Hello Leszek, thank for doing this research.

You are explaining how a CSR could be created better or more correct, but I'm not convinced it's worth the effort.

In my understanding, CAs have certain requirements, operated under certain policies. Those influence what information a CA is willing to allow in a certificate.

In theory, a CSR could describe a certificate in much detail, with a DN, attributes and extensions. However, the CA might not be willing to sign it in this way.

For example, in the past I saw CAs that were unwilling to include the applicant's real name in the certificate. I saw that in the context of certificates that were issued for free, and only the email address was checked. That CA had only checked the email address of the applicant. Probably, because the CA didn't even attempt to verify the accuracy of the name or organization fields, they weren't willing to create a certification for those attributes.

You are arguing that it's better to implement something "the right way", instead of iterating.
I don't agree with this suggestion here, because it isn't a small amount of work to implement a UI that would allow a Thunderbird user to create any possible kind of CSR.

Right now, I can only spend a small amount of time on this feature. I believe that having a simple implementation would already be a major improvement over today's status quo, which doesn't have any implementation at all.

If the simple implementation is sufficient for most users, then it's an unnecessary complexity to have additional questions in the UI.

I suggest to start with this initial step. I think it's fine to iterate later on, if necessary. If we make an initial version available, then users of Thunderbird can try it, and give us feedback what's missing or what isn't working.

I will consider your suggestion to move the email address to the SAN extension. It shouldn't be much work, we already have some code as part of the NSS utilities that we could reuse. My only concern here is: If we move it to the SAN, then what should we place into the DN? Is it ok to leave it empty?

You suggested to combine the CSR creation with the OpenPGP code. I don't see the benefit here. I rather see risk of confusion, because different questions are asked for OpenPGP key generation (e.g. key expiration).

... and only the email address was checked. That CA had only checked the email address of the applicant.
...
My only concern here is: If we move it to the SAN, then what should we place into the DN? Is it ok to leave it empty?

NULL SEQUENCE (empty) I guess. You would have to ask someone more experienced.

I agree that the CA can reject everything from the CSR and carry out the process only on the public key from the CSR. We can provide information (needed for verification) in various ways. We can even send this information via carrier pigeon to the CA. Before doing so, let's seal the scroll with the family seal. We can also put unusual things in the CSR. See: EDWARDS_csr.tar.gz. There is no mechanism in the CSR to deliver the DH key to the CA (at least I haven't found something like that), so I found a trick to put 2 public keys in the CSR and sign with a signable private key (EdDSA). I am sure that no CA will support EdDH keys/certificates if there is no interest and ready-made solutions. So, we provide proof of possession and may additionally include personal information for verification. We sign this information with a private key. I think that's what CSR is all about.

You present your implementation of CSR creation, and I present a counter-proposal. Whether it is relevant, needed and to whom, I don't know, but the idea comes from the logic and specification. CSR is old and you have seen other programs that create CSRs on the same principle as my ideas (for example, Kleopatra and DigiCert). Or rather my ideas are based on these programs. This means that the way is verified, established. I call it "the right way." This "right method" has additional advantages: the program recognizes additional DNs and attributes, it is modular (you add what you want to the CSR) and you further improve the NSS (see bugs).

But it is none of my business how it will be done in the mail program. I just look and suggest ideas (which I verify beforehand). I'm not going to fight a war over it ;) After all, my examples can be used to fix bugs or introduce new features in NSS (if anyone cares), or in Th. later.

It's a shame that only one person is working on such a feature.

A question for someone more experienced: The "SMIME BRs" specification is created for the CA and defines what the target certificate should look like (simplified). Does it seem necessary, useful or thoughtful to construct a CSR based on this specification (SubjectDNs, types of keys) in the mail program? Or more generally: is it even worth creating a CSR with personal data in such a program?

Flags: needinfo?(bwilson)

I'm still looking into this. Thanks, Ben

Here are some posts re: CSR contents from discussions on the CA/B Forum's Public S/MIME Working Group list - https://lists.cabforum.org/pipermail/smcwg-public/2023-October/thread.html, including mention that section 3, step 8, of RFC 8823 (Informational: ACME for S/MIME) requires an email address in the CSR. I'd advise that CSRs should at least include the email address in the Subject Alternative Name. Other fields can be added to the TBS certificate, after verification, by the CA. Types of keys would depend on what Thunderbird supports.

Flags: needinfo?(bwilson)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: