lcp / mokutil

The utility to manipulate machine owner keys
GNU General Public License v3.0
60 stars 37 forks source link

ff20a53a mokutil: do the CA check #51

Open hramrach opened 2 years ago

hramrach commented 2 years ago

Why is this?

First we have commit ff20a53a111fe3e027da7250175b7ef09ce3b1da Author: Gary Lin glin@suse.com Date: Thu Aug 27 14:11:56 2020 +0800

mokutil: do the CA check

Check whether th CA cert is already enrolled in the key database before
enrolling the key.

The check can be disabled with "--ignore-ca-check".

and then

commit 235e92a1d3e0f32f7be44aa0f37d7f3041306ccc Author: Gary Lin glin@suse.com Date: Wed Sep 2 16:09:04 2020 +0800

mokutil: disable CA check by default

The SUSE PTF certificate is also issued by SUSE CA, so enabling CA check
by default would ignore the enrollment of the PTF certificates and the
PTF would be unloadable.

Flip "--ignore-ca-check" to "--ca-check" and set force_ca_check to 0 by
default.

which shows that the fact that the CA is enrolled is irrelevant and the kernel is not bootable anyway.

hramrach commented 2 years ago

@joeyli

joeyli commented 2 years ago

What I knew is that the check CA is for avoiding the limited space of NVRAM be wasted. Because the CA of kernel signkey maybe is already embedded in shim.

There have two reason for saving the NVRAM space:

hramrach commented 2 years ago

But then it's made not default because even when CA is already embedded in shim (at least as far this check is concerned) kernel is still not bootable unless its key is enrolled.

There is one way to save limited space and memory wear that is reliable: not enroll keys already enrolled.

Apparently all other schemes failed.

Does shim even support verification of key by CA?

If it does then one of the things is broken: this CA check, that CA support in shim.

lcp commented 2 years ago

The CA check was introduced to avoid enrolling the distro sign keys which is not necessary in MOK. To support the signature verification by CA, the CA key has to be in the EFI signature. Could you check if the CA key is properly built in the signature?

lnussel commented 1 year ago

This is related to https://bugzilla.suse.com/show_bug.cgi?id=1173115

hramrach commented 1 year ago

I am not aware of any embedding of CA key into the efi signature.

The EFI signature is obtained as raw RSA signature blob by pesign-obs-integration, and that signature blob is wrapped into PKCS#7 structure based on the project certificate obtained from OBS.

But suppose that we take care to add CA signature to the project certificate, and pesign-obs-integration embeds it into the kernel signature so that shim can determine that the kernel is in fact signed by a certificate issued by SUSE CA.

We also support installing kernels that are NOT signed by the SUSE release project certificate. It may be a PTF, a test kernel, a custom built kernel.

These kernels are also supposed to be able to load modules that are signed by the SUSE key, but the key is not enrolled in MOK because of the CA check and the in-kernel check.

It's possible to embed the SUSE certificate in addition to the project certificate in the kernel so that loading official KMPs works, and for PTFs this is likely done. However, for general test and custom kernel builds this does not happen.

We might ship the SUSE certificate in the kernel source but it does get rotated sometimes, and then it needs to be updated, and also then it does not help with loading official modules when the kernel and modules are out of sync.

We could embed the SUSE CA certificate into the kernel and enable the secondary keyring so that keys signed by the CA can be loaded into the secondary keyring, and load them into the kernel instead but this is not done.

lcp commented 1 year ago

The CA check was introduced to avoid enrolling the distro sign keys which is not necessary in MOK. To support the signature verification by CA, the CA key has to be in the EFI signature. Could you check if the CA key is properly built in the signature?

Sorry, this comment is misleading. I was thinking about the full certificate chain in the signature. However, the CA key is not necessary to be in the signature. The sign key alone is sufficient.

The point to introduce the CA check is mainly to skip the key enrolling during the kernel installation. The kernel built-in sign key is not necessary to be in MOK since it's already in the kernel key ring. As for KMP, the CA check could introduce some problem since KMP may not be signed by the same key. That's why the CA check is disabled by default and only enabled for kernel installation.

hramrach commented 1 year ago

Which means you should not be able to kexec official kernel from non-official one, for example. The official kernels are signed by a key that passes the CA check and thus is not enrolled but unofficial kernels do not know about that key.

hramrach commented 1 year ago

The CA check was introduced to avoid enrolling the distro sign keys which is not necessary in MOK. To support the signature verification by CA, the CA key has to be in the EFI signature. Could you check if the CA key is properly built in the signature?

Sorry, this comment is misleading. I was thinking about the full certificate chain in the signature. However, the CA key is not necessary to be in the signature. The sign key alone is sufficient.

Of course it has to be in the signature. If the CA check passes the signing certificate is NOT enrolled which means only the signature and the CA certificate is available to shim to decide if the signature is valid. Then the signature must include the certificate chain information, including signature made with the CA key that validates the signing certificate, and thus information about the CA key that made the signature.

lcp commented 1 year ago

Which means you should not be able to kexec official kernel from non-official one, for example. The official kernels are signed by a key that passes the CA check and thus is not enrolled but unofficial kernels do not know about that key.

I see your point, and this sounds like a missing feature in kernel to me. The shim built-in CA is exported to MokListRT. If kexec verifies the kernel image with CA as shim does, you don't need to enroll any sign key into MokList.

lcp commented 1 year ago

The CA check was introduced to avoid enrolling the distro sign keys which is not necessary in MOK. To support the signature verification by CA, the CA key has to be in the EFI signature. Could you check if the CA key is properly built in the signature?

Sorry, this comment is misleading. I was thinking about the full certificate chain in the signature. However, the CA key is not necessary to be in the signature. The sign key alone is sufficient.

Of course it has to be in the signature. If the CA check passes the signing certificate is NOT enrolled which means only the signature and the CA certificate is available to shim to decide if the signature is valid. Then the signature must include the certificate chain information, including signature made with the CA key that validates the signing certificate, and thus information about the CA key that made the signature.

For the signature to be verified by shim or shim protocol, the sign key is sufficient. For example:

$ pesign -i /boot/efi/EFI/opensuse/grub.efi -e grub.sig
$ openssl pkcs7 -in grub.sig -inform der -print_certs
subject=CN = SUSE Linux Enterprise Secure Boot Signkey, C = DE, L = Nuremberg, O = SUSE Linux Products GmbH, OU = Build Team, emailAddress = build@suse.de

issuer=CN = SUSE Linux Enterprise Secure Boot CA, C = DE, L = Nuremberg, O = SUSE Linux Products GmbH, OU = Build Team, emailAddress = build@suse.de

-----BEGIN CERTIFICATE-----
MIIFBDCCA+ygAwIBAgIJAO2HhbeP/BJ/MA0GCSqGSIb3DQEBCwUAMIGmMS0wKwYD
VQQDDCRTVVNFIExpbnV4IEVudGVycHJpc2UgU2VjdXJlIEJvb3QgQ0ExCzAJBgNV
BAYTAkRFMRIwEAYDVQQHDAlOdXJlbWJlcmcxITAfBgNVBAoMGFNVU0UgTGludXgg
UHJvZHVjdHMgR21iSDETMBEGA1UECwwKQnVpbGQgVGVhbTEcMBoGCSqGSIb3DQEJ
ARYNYnVpbGRAc3VzZS5kZTAeFw0yMjA2MDIyMjUyNTBaFw0zMjEyMzAyMjUyNTBa
MIGrMTIwMAYDVQQDDClTVVNFIExpbnV4IEVudGVycHJpc2UgU2VjdXJlIEJvb3Qg
U2lnbmtleTELMAkGA1UEBhMCREUxEjAQBgNVBAcMCU51cmVtYmVyZzEhMB8GA1UE
CgwYU1VTRSBMaW51eCBQcm9kdWN0cyBHbWJIMRMwEQYDVQQLDApCdWlsZCBUZWFt
MRwwGgYJKoZIhvcNAQkBFg1idWlsZEBzdXNlLmRlMIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEAwDNrJ6NGA3ca+mIR0xPimAmBiC0p/LKKFf2nM64gGr2p
l+VYf4tZONMJpeJSASChD9KEuDFpAfKJm0S+lvmMUEJSxdj6p8ynLtypcE/k9+TP
5j8STpdA5L+P9RIt0r4USGUNf9WT5CfLmQVx6EWjjnUqP6H7t4gS76NXxI6ODu7G
ihPiG4acjYxtgAmErXHP42Tk8srzYN+RVddZLnKQWhLWahuomq8320iHm2biZ01B
coHFZnPO62fw5LHeig94UXixf7NPgwPBr9owuKw4WouDfH4nCY6KEOZG+flF/ME+
6TuExYRCPwG3wXgOmGHNYyH8vAvR9s99sZFIGXYdrwIDAQABo4IBLDCCASgwDAYD
VR0TAQH/BAIwADAdBgNVHQ4EFgQUCsYrHz9TQnETJYbinTsQQVkcgkowgdMGA1Ud
IwSByzCByIAU7KsNQsRWz3cENrlzmThill6HJi+hgaykgakwgaYxLTArBgNVBAMM
JFNVU0UgTGludXggRW50ZXJwcmlzZSBTZWN1cmUgQm9vdCBDQTELMAkGA1UEBhMC
REUxEjAQBgNVBAcMCU51cmVtYmVyZzEhMB8GA1UECgwYU1VTRSBMaW51eCBQcm9k
dWN0cyBHbWJIMRMwEQYDVQQLDApCdWlsZCBUZWFtMRwwGgYJKoZIhvcNAQkBFg1i
dWlsZEBzdXNlLmRlggEBMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEF
BQcDAzANBgkqhkiG9w0BAQsFAAOCAQEAgB40iq70uOw6SLvHhZb8NpJuETDdfQzE
RuEDtd0bHgHfhvjLpzaHP8ZVLHr8lpsyaLwVE4598cmys8Zn1vvkCQOo4LwwVILR
8Jar2gvgJ2xqTUVU3bYhr+MaGpScbDyK6n2Kb8/vuEpaHHTJWMx5js2jGh1G2+AG
hohfQX+K5UPUKyBRfiDwcZhq2JpCOq5F/SDbm1kpX5dwzu/Y0yDYfukz4tqvpq+S
8SW1+fv37Fbch6DjFw51ALUtkfPmNShlgcub3deyD0vZvBWxlJRllBv16c+yLXSx
1XmOY8MOEntYKKgKb4zpNKAnCwP7yc/R5Chk1tvLgvoymbxAKfkd3Q==
-----END CERTIFICATE-----

There is only SUSE sign key in the grub2 signature and shim still can verify it as long as the CA is in db or built-in.

joeyli commented 1 year ago

Which means you should not be able to kexec official kernel from non-official one, for example. The official kernels are signed by a key that passes the CA check and thus is not enrolled but unofficial kernels do not know about that key.

I see your point, and this sounds like a missing feature in kernel to me. The shim built-in CA is exported to MokListRT. If kexec verifies the kernel image with CA as shim does, you don't need to enroll any sign key into MokList.

Base on kernel community's discussion, not every keys (includes CA) be enrolled to MOK can be used for any purpose. Please reference:

https://lore.kernel.org/all/de0b6e61-2f6e-c215-65a9-428c3bf1bfb8@gmail.com/

and

https://static.sched.com/hosted_files/lssna2022/18/LSS%202022%20trust%20and%20keyrings.pdf

Base on the above plan, the CA in MOK (and only CA) will be loaded to secondary keyring. Then it can be used to verify kexec, modsign and other keys will be enrolled to .ima or .secondary keyring. Kernel doesn't support direct use CA to verify CA-verified-signkey signed kernel. CA can only verify another signkey when enroll it to secondary keyring.

hramrach commented 1 year ago

Base on the above plan, the CA in MOK (and only CA) will be loaded to secondary keyring. Then it can be used to verify kexec, modsign and other keys will be enrolled to .ima or .secondary keyring. Kernel doesn't support direct use CA to verify CA-verified-signkey signed kernel. CA can only verify another signkey when enroll it to secondary keyring.

And there is nothing adding these keys into the secondary keyring, even on OS releases on which we do have it enabled.

lcp commented 1 year ago

Well, mokutil doesn't stop you from enrolling the sign key unless --ca-check is specified. For the majority of users, the sign key is not necessary in MOK because the built-in CA in shim is sufficient, and the sign key enrolling right after kernel upgrade could easily confuse the normal user. Furthermore, based on Joey's comment, the CA in MOK can be used to authorize the sign key into .secondary keyring, so that you can enroll the sign key on demand. This is even better because it prevents rebooting the system and doesn't consume the precious firmware storage.