Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to add S/MIME certificate? #3840

Closed
protist opened this issue May 4, 2023 · 6 comments
Closed

How to add S/MIME certificate? #3840

protist opened this issue May 4, 2023 · 6 comments
Labels

Comments

@protist
Copy link

protist commented May 4, 2023

I regularly receive emails from a colleague who signs with S/MIME. At the beginning of each email NeoMutt says

[-- Begin signature information --]
*BAD* signature from:
C=<redacted>,<redacted>=#<redacted>,OU=<redacted>,O=<redacted>,CN=<redacted>
                 aka: <<redacted>>
             created: <redacted>
[-- End signature information --]

and at the bottom status bar it says S/MIME signature successfully verified. Hence, I think that S/MIME is working, but the signature/certificate is not in my database. I would like to add the signature to my database, so that NeoMutt consistently says GOOD signature. I'm a total novice to S/MIME, but I've spent about an hour trying to work this out.

These emails always have a smime.p7s file attached. My understanding is that this is a DER-encoded PKCS7 public key, and I need to convert it to a PEM-encoded PKCS7 public key. Hence, I save the attachment, then

openssl pkcs7 -inform der -in /tmp/smime.p7s -print_certs > /tmp/smime.crt

This file looks okay,

subject=CN = <redacted>, O = <redacted>, OU = "<redacted>", emailAddress = <redacted>, C = <redacted>
issuer=CN = <redacted>, O = <redacted>, OU = "<redacted>", emailAddress = <redacted>, C = <redacted>
-----BEGIN CERTIFICATE-----
<redacted>
-----END CERTIFICATE-----

N.B. the subject and issuer details are identical.

I then initialised the smime database using NeoMutt's smime_keys.

In ~/.mutt/muttrc

set smime_keys = "~/.smime/keys"
set smime_certificates = "~/.smime/certificates"
set smime_ca_location = "~/.smime/ca"

Run /usr/lib/neomutt/smime_keys init, which created ~/.smime.

And then now I was stuck. I tried the following, which failed.

$ /usr/lib/neomutt/smime_keys add_cert /tmp/smime.crt

You may assign a label to this key, so you don't have to remember
the key ID. This has to be _one_ word (no whitespaces).

Enter label: <redacted>
Found 0 certificate chains

The following also failed

$ /usr/lib/neomutt/smime_keys add_pem /tmp/smime.crt
Not all contents were bagged. can't continue. at /usr/lib/neomutt/smime_keys line 605.

I also tried the following, which added nothing

$ gpgsm --import /tmp/smime.crt
gpgsm: total number processed: 1
gpgsm:              unchanged: 1

FWIW I also found NeoMutt's smime.rc, but this didn't seem that relevant to my problem.

How can I get NeoMutt to verify these emails as GOOD?

@protist protist added the type:question Question label May 4, 2023
@rayfordshire
Copy link
Contributor

Sorry for the long wait.

The message you cite with the "BAD signature" is the (raw) output from the backend program (either gpg or openssl). The message in the statusbar is by neomutt interpreting the return code of the program.

It is generally recommended to use gpgme as backend (set crypt_use_gpgme = yes instead of the legacy smime backend (smime_*_command and some smime_* options).

To get gpgme working (which accesses the same database as gpgsm) you need to:
a) set crypt_use_gpgme = yes in your neomuttrc (this is the default unless you changed it, so can usually be omitted)

b) import the root certificate (and possibly some intermediate certificates) to the certificate storage using gpgsm

gpgsm --import <certificate>

Usually (but not always) an S/MIME signed/encrypt email comes with all non-root certificates which get automatically imported into the database once you read the e-mail.

c) set up trust for the root certificate, please see section "setting up trust" in https://www.claws-mail.org/faq/index.php/S/MIME_howto (and maybe #3567)

@protist
Copy link
Author

protist commented Nov 27, 2023

Sorry for the long wait.

No worries. Thank you for the reply. FWIW I had a single contact who used S/MIME, and they no longer use it, so this problem is no longer relevant for me. I'm happy to help out for future users though.

a) set crypt_use_gpgme = yes in your neomuttrc (this is the default unless you changed it, so can usually be omitted)

I don't have any reference to crypt_use_gpgme in my muttrc, so I assume it's all fine.

gpgsm --import <certificate>

This seems to be the same command I mention in my OP, where I tried to import the PEM-encoded PKCS7 public key. This failed for me previously, but I think that was because I already had the certificate. I tried deleting the cert and re-importing, and this now seemed to work fine.

c) set up trust for the root certificate

As per your first link, I ran gpgsm --list-keys 2>/dev/null | grep fingerprint | awk '{print $2 " S"}' > ~/.gnupg/trustlist.txt. I could manually confirm that the fingerprint of the relevant contact was present in this file. I then sent a SIGHUP (as per the first link), then a SIGTERM , then gpgconf --reload gpg-agent (as per the second link), then another SIGTERM for good measure. None of these options seemed to help.

FWIW in mutt, I can see down the bottom it says

S/MIME signature successfully verified

However at the top of the message itself it says

*BAD* signature from:

@rayfordshire
Copy link
Contributor

FWIW in mutt, I can see down the bottom it says

S/MIME signature successfully verified

However at the top of the message itself it says

*BAD* signature from:

If I have to guess, then your e-mail was tempered with (not necessarily maleficent). The output at the top of the message is the output of gpg not (neo)mutt. Could please verify that the email has a valid signature. I described the process using gpgsm and openssl in #3567 . (You can also use openssl alone but I don't know the command off the top of my head, so you have to search for it yourself.)

@protist
Copy link
Author

protist commented Dec 4, 2023

Thanks again @rayfordshire.

I can't seem to get your code working, but maybe this is informative? Following your linked instructions... In mutt

<pipe-command>cat > /tmp/signed-mail.eml

Then save the attachment smime.p7s

Attempt to extract the body.

$ openssl cms -verify -in signed-mail.eml > openssl-body
CMS Verification failure
<redacted>:error:<redacted>:CMS routines:cms_signerinfo_verify_cert:certificate verify error:crypto/cms/cms_smime.c:289:Verify error: self-signed certificate

tried again with -noverify Do not verify the signers certificate of a signed message.

$openssl cms -verify -noverify -in signed-mail.eml > openssl-body
CMS Verification successful

Attempt to verify with gpgsm

$ gpgsm -n --verify smime.p7s openssl-msg
gpgsm: can't open 'openssl-msg': No such file or directory

Was that a typo in your instructions?

$ gpgsm -n --verify smime.p7s openssl-body
gpgsm: Signature made <YYYY-MM-DD HH:MM:SS> UTC
gpgsm:                using rsa2048 key <redacted>
gpgsm: issuer certificate is not marked as a CA
gpgsm: invalid certification chain: Bad CA certificate

I guess that failed? Keep going anyway.

$ gpgsm -n --verify --assume-base64 smime.p7s.base64 openssl-body
gpgsm: can't open 'smime.p7s.base64': No such file or directory

I also tried the above without -n, but no smime.p7s.base64 was created.

@rayfordshire
Copy link
Contributor

I apologise for the late reply, busy time around here.

Attempt to verify with gpgsm

$ gpgsm -n --verify smime.p7s openssl-msg
gpgsm: can't open 'openssl-msg': No such file or directory

Was that a typo in your instructions?

Opps, yes it was.


From the looks of it, it seems like the chain of trust cannot be established.
Usually a certificate chain looks like:

+----------------+                  +---+                 +---+                                    +-------+
|your certificate|  <--signed-by--  |CA1|  <--signed-by-- |CA2|  <--signed-by-- ... <--signed-by-- |root CA| (signed by itself)
+----------------+                  +---+                 +---+                                    +-------+

The first certificate "your certificate" is the one you have or get from your contact.
This is the one you occasionally import.

The last certificate "root CA" is usually bundled by the OS in /etc/certificates and associated with a well-known cooperation (e.g. Let's Encrypt, VeriSign, etc)
From the whole chain you only need to trust the "root CA" (e.g. via trustlist.txt).
The others "inherit" the trust via a valid signature.

From your quotes it seems like your contact made a self-signed certificate, i.e. they are the root CA and the chain collapsed to a single entry:

+----------------+
|your certificate| (signed by itself)
+----------------+

To instruct openssl that a certificate is a root certificate, you can use

$ openssl cms -verify -CAfile path/to/your-ca-certificates -in signed-mail.eml > openssl-body

where your-ca-certificates is a file with the certificate (I guess in PEM format).

gpgsm seems to have an additional check/requirement for root certificates (i.e. self-signed certificates) but maybe adding "relax"[0] into trustfile.txt helps.
From the documentation:

Relax checking of some root certificate requirements. As of now this flag allows the use of root certificates with a missing basicConstraints attribute (despite that it is a MUST for CA certificates) and disables CRL checking for the root certificate.

The trustfile.txt entry should look like

12:34:...:EE:FF S relax

where 12:34:...:EE:FF is the fingerprint of the self-signed certificate.

After modifying trustfile.txt do not forget to reload your gpg-agent, e.g. via sending SIGHUP signal or gpgconf --reload gpg-agent or both. ;-)

[0] https://www.gnupg.org/documentation/manuals/gnupg/Agent-Configuration.html

@protist
Copy link
Author

protist commented Feb 7, 2024

Thanks so much @rayfordshire and I apologise for my late reply!

I spent another hour or so troubleshooting this, but I still couldn't really get this to play well. Sorry, I'm just going to let this lapse since the contact no longer uses S/MIME. Hopefully some of these comments will be helpful for others. I really appreciate your help.

@protist protist closed this as completed Feb 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants