Bug 1209006 - Document how to secureboot-sign manually-built kernel modules on TW kernel >= 6.2.1
Document how to secureboot-sign manually-built kernel modules on TW kernel >=...
Status: NEW
: 1208939 1208966 (view as bug list)
Classification: openSUSE
Product: openSUSE Tumbleweed
Classification: openSUSE
Component: Kernel
Current
Other Other
: P1 - Urgent : Critical (vote)
: ---
Assigned To: Joey Lee
E-mail List
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2023-03-07 12:26 UTC by Stefan Dirsch
Modified: 2023-03-24 15:30 UTC (History)
18 users (show)

See Also:
Found By: ---
Services Priority:
Business Priority:
Blocker: ---
Marketing QA Status: ---
IT Deployment: ---


Attachments
MOK-nvidia-driver-G06-525.89.02-7.1-default.der.tw (898 bytes, application/octet-stream)
2023-03-07 17:11 UTC, Stefan Dirsch
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Stefan Dirsch 2023-03-07 12:26:37 UTC
Now that we added lockdown patches to our kernel with version 6.2.1 breaking nvidia driver packages it would be time to let our users/developers know how to secureboot-sign manually-built kernel modules (vmware, nvidia, etc.). You can see that there is a need in this mail thread on opensuse-factory ML. :-(

  https://lists.opensuse.org/archives/list/factory@lists.opensuse.org/thread/APEWGMWSEABQ5ZFGZ2I5M3MWJERZ4K7I/

Documentation for vmware, that doesn't work for TW 6.2.1 kernels

  https://kb.vmware.com/s/article/2146460
  (well, there is missing a -addext "extendedKeyUsage=codeSigning needed already for Leap kernels; so this seems to be outdated
    anyway)

Things that are working for Leap >= 15.2 are:

 flavor=default
    privkey=$(mktemp /tmp/MOK.priv.XXXXXX)
    pubkeydir=/var/lib/nvidia-pubkeys
    pubkey=$pubkeydir/MOK-nvidia-driver-G06-525.89.02-7.1-$flavor.der

    # make sure creation of pubkey doesn't fail later
    test -d pubkeydir || mkdir -p $pubkeydir

    # Create a key pair (private key, public key)
    openssl req -new -x509 -newkey rsa:2048 \
                -keyout $privkey \
                -outform DER -out $pubkey -days 1000 \
                -subj "/CN=Local build for nvidia-driver-G06 525.89.02 on $(date+"%Y-%m-%d")/" \
                -addext "extendedKeyUsage=codeSigning" \
                -nodes

    # Install the public key to MOK
    mokutil --import $pubkey --root-pw

    kver=6.2.1-1-default
    # Sign the Nvidia modules (weak-updates appears to be broken)
    for i in /lib/modules/$kver/updates/nvidia*.ko; do
      /lib/modules/$kver/build/scripts/sign-file sha256 $privkey $pubkey $i
    done

    # cleanup: private key no longer needed
    rm -f $privkey

With the TW kernel this results in

# dmesg -c > /dev/null
# modprobe nvidia
modprobe: ERROR: could not insert 'nvidia': Operation not permitted
# dmesg
[   58.707747] lockdown_is_locked_down: 2 callbacks suppressed
[   58.707751] Lockdown: modprobe: unsigned module loading is restricted; see
man kernel_lockdown.7
# modinfo nvidia
filename:       /lib/modules/6.2.1-1-default/updates/nvidia.ko
firmware:       nvidia/525.89.02/gsp_tu10x.bin
firmware:       nvidia/525.89.02/gsp_ad10x.bin
alias:          char-major-195-*
version:        525.89.02
[...]

Takashi asked me to look into our kernel-install-tools. I had a quick look, but I need to say I don't understand them.

1) It works with one file /path/to/certificate for both private and public key? How is this possible? We want to remove private key right
   after signing but keep public key on the system.
2) There is only a tool (sbtool-sign-kernel) to sign the kernel image, not the kernel modules? Or how is this supposed to work?
3) Signing of modules in KMPs is apparently not being done by the tools in this package, so maybe these are not the right tools at all?
Comment 1 Stefan Dirsch 2023-03-07 17:11:47 UTC
Created attachment 865340 [details]
MOK-nvidia-driver-G06-525.89.02-7.1-default.der.tw

Certificate created on TW. Look at it via  'openssl x509 -in <filename> -text'.
Comment 2 Stefan Dirsch 2023-03-07 17:13:49 UTC
(In reply to Stefan Dirsch from comment #1)
> Created attachment 865340 [details]
> MOK-nvidia-driver-G06-525.89.02-7.1-default.der.tw
> 
> Certificate created on TW. Look at it via  'openssl x509 -in <filename>
> -text'.

For some reason reading this certificate works for me on TW, but no on Leap 15.4

# openssl x509 -in MOK-nvidia-driver-G06-525.89.02-7.1-default.der.tw -text
unable to load certificate
139783333067776:error:0909006C:PEM routines:get_name:no start line:crypto/pem/pem_lib.c:745:Expecting: TRUSTED CERTIFICATE

But that's not the topic here ...
Comment 3 Stefan Dirsch 2023-03-07 17:40:08 UTC
(In reply to Stefan Dirsch from comment #2)
> For some reason reading this certificate works for me on TW, but no on Leap
> 15.4
> 
> # openssl x509 -in MOK-nvidia-driver-G06-525.89.02-7.1-default.der.tw -text
> unable to load certificate
> 139783333067776:error:0909006C:PEM routines:get_name:no start
> line:crypto/pem/pem_lib.c:745:Expecting: TRUSTED CERTIFICATE
> 
> But that's not the topic here ...

Use 'openssl x509 -inform DER -in <filename> -text' instead ...
Comment 4 Stefan Dirsch 2023-03-07 19:08:15 UTC
Michal Suchanek just wrote in the email thread on factory ML

---
Shouldn't this be set:

config/x86_64/default:#
CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY is not set

The MOK keys get added to th secondary keyring, not primary.
---

Could this be the issue here?
Comment 5 Stefan Dirsch 2023-03-07 19:21:57 UTC
At least on Leap 15.4, where signed kernel modules work, it's set.

15.4 $ zcat /proc/config.gz |grep CONFIG_IMA_KEY
CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY=y

whereas on TW it's not.

TW $ zcat /proc/config.gz |grep CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY
# CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY is not set
Comment 6 Michal Suchanek 2023-03-07 19:45:56 UTC
On Leap we don't need the secondary keyring at all, we have a downstream patch that loads the MOK keys into platform keyring, and verifies modules with platform keyring.

In upstream the MOK keys are loaded into machine keyring which then should get loaded into secondary keyring.

This option is for loading additional keys (which the name does not reflect) in a specific way different from the default (which the name does not reflect) and is incompatible with machine keyring (which would have to be patched out to enable it).

Does not seem to work for me, anyway:

cat /proc/keys | grep machine
31db47ec I------     1 perm 1f0b0000     0     0 keyring   .machine: empty
Comment 7 Stefan Dirsch 2023-03-07 20:12:07 UTC
*** Bug 1208966 has been marked as a duplicate of this bug. ***
Comment 8 Stefan Dirsch 2023-03-07 20:12:37 UTC
*** Bug 1208939 has been marked as a duplicate of this bug. ***
Comment 9 Joey Lee 2023-03-08 08:13:02 UTC
(In reply to Michal Suchanek from comment #6)
> On Leap we don't need the secondary keyring at all, we have a downstream
> patch that loads the MOK keys into platform keyring, and verifies modules
> with platform keyring.

The CONFIG_INTEGRITY_MACHINE_KEYRING .machine keyring needs .secondary trusted keyring. 

> 
> In upstream the MOK keys are loaded into machine keyring which then should
> get loaded into secondary keyring.

Looks it's not. 

Base on v6.2 kernel, keys in .machine keyring still must be trusted(signed) by key in built-in/secondary keyring. It applies restrict_link_to_ima and depends on CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY.

If the key can not pass the restriction check, kernel will put to key to .platform keyring. The logic is in add_to_machine_keyring(), but I didn't test it yet.

So, currently the .machine keyring is NOT useful for loading a MOK-signed kernel module. I think all MOKs will be loaded to .platform keyring. Unless Eric Snowberg's MOK CA patch be accepted:

Eric Snowberg <eric.snowberg@oracle.com>
[PATCH v4 0/6] Add CA enforcement keyring restrictions
https://lore.kernel.org/lkml/20230207025958.974056-1-eric.snowberg@oracle.com/
[PATCH v4 6/6] integrity: machine keyring CA configuration

> 
> This option is for loading additional keys (which the name does not reflect)
> in a specific way different from the default (which the name does not
> reflect) and is incompatible with machine keyring (which would have to be
> patched out to enable it).
> 
> Does not seem to work for me, anyway:
> 
> cat /proc/keys | grep machine
> 31db47ec I------     1 perm 1f0b0000     0     0 keyring   .machine: empty

Kernel will check the existence of MokListTrustedRT. So we need to run "mokutil --trust-mok", otherwise all MOK will go to .platform keyring. But, the above tracing, unless the MOK be signed by built-in key. Then it still go to .platform keyring.
Comment 10 Joey Lee 2023-03-08 08:28:14 UTC
(In reply to Michal Suchanek from comment #6)
> On Leap we don't need the secondary keyring at all, we have a downstream
> patch that loads the MOK keys into platform keyring, and verifies modules
> with platform keyring.
> 

On the other hand, as Michal mentioned, SLE/Leap applied downstream patch:

patches.suse/KEYS-Make-use-of-platform-keyring-for-module-signatu.patch

This patch allows modsign function mod_verify_sig() uses .platform keyring to verify kernel module. We didn't have this patch in openSUSE Tumbleweed yet.

I have checked the following kernels from different distros, all of them are applied the same downstream patch:

Ubuntu    ubuntu-stable-kinetic
              no CONFIG_INTEGRITY_MACHINE_KEYRING

CentOS Stream 9    kernel linux-5.14.0-214.el9.x86_64
              no CONFIG_INTEGRITY_MACHINE_KEYRING

Fedora 37   kernel-6.2.2-301.fc38.src.rpm
              CONFIG_INTEGRITY_MACHINE_KEYRING=y

Fedora 37 has set CONFIG_INTEGRITY_MACHINE_KEYRING, but it still applied downstream patch to allow .platform keyring be used to verify kernel modules.

We can also apply this patch to openSUSE Tumbleweed, but this patch may never be accepted by kernel upstream. Because in Eric Snowberg's "Add CA enforcement keyring restrictions" solution, only CA in MOK can be put to .secondary keyring.  Other non-CA MOKs still can not be used to verify kernel module. User needs to use keyctl to add it to .secondary keyring after the CA MOK be added.

If we don't apply downstream patch and choice waiting Eric's solution is accepted. Then the only solution is disabling secure boot currently.
Comment 11 Stefan Dirsch 2023-03-08 12:29:52 UTC
Tried "mokutil --trust-mok". After enrolling. Didn't help. Deleted the key from Mok. Then re-enrolling it again. Didn't help either.
Comment 12 Joey Lee 2023-03-08 12:36:04 UTC
(In reply to Stefan Dirsch from comment #11)
> Tried "mokutil --trust-mok". After enrolling. Didn't help. Deleted the key
> from Mok. Then re-enrolling it again. Didn't help either.

I am porting patches.suse/KEYS-Make-use-of-platform-keyring-for-module-signatu.patch to openSUSE Tumbleweed kernel. We need it for Nvidia driver.

But we will need to change the rpm scripts of Nvidia driver again when Eric Snowberg's patch set be merged on mainline if we want to follow upstream's approach.
Comment 13 Stefan Dirsch 2023-03-08 12:39:54 UTC
For me this looks like we are't prepared at all for supporting 3rd party kernel modules signed with their own MOK certificates with this kernel update with lockdown patches enabled.

So I suggest to revert this and work on how to support this for a later kernel update with lockdown patches re-enabled.
Comment 14 Stefan Dirsch 2023-03-08 12:41:34 UTC
(In reply to Joey Lee from comment #12)
> (In reply to Stefan Dirsch from comment #11)
> > Tried "mokutil --trust-mok". After enrolling. Didn't help. Deleted the key
> > from Mok. Then re-enrolling it again. Didn't help either.
> 
> I am porting
> patches.suse/KEYS-Make-use-of-platform-keyring-for-module-signatu.patch to
> openSUSE Tumbleweed kernel. We need it for Nvidia driver.

Thanks for taking care of this.

> But we will need to change the rpm scripts of Nvidia driver again when Eric
> Snowberg's patch set be merged on mainline if we want to follow upstream's
> approach.

Ok. But I need to know in which way. And I would like to have the time to prepare this beforehand ...
Comment 15 Martin Wilck 2023-03-08 17:42:13 UTC
(In reply to Joey Lee from comment #9)

> > In upstream the MOK keys are loaded into machine keyring which then should
> > get loaded into secondary keyring.
> 
> Looks it's not. 
> 
> Base on v6.2 kernel, keys in .machine keyring still must be trusted(signed)
> by key in built-in/secondary keyring. It applies restrict_link_to_ima and
> depends on CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY.

system_trusted_keyring_init() uses get_builtin_and_secondary_restriction() as restriction for the secondary keyring. This resolves to  restrict_link_by_builtin_secondary_and_machine() if CONFIG_INTEGRITY_MACHINE_KEYRING is set, (and restrict_link_by_builtin_and_secondary_trusted otherwise).

But machine_keyring_init() -> integrity_init_keyring() -> _integrity_init_keyring() uses restrict_link_to_ima, which resolves to restrict_link_by_builtin_and_secondary_trusted(). 

So keys could be added from the machine keyring to the secondary keyring without being trusted by the secondary keyring beforehand, but such keys could never have been added to the machine keyring in the first place.

That looks like an upstream bug to me.

TBH, I fail to understand the entire concept. A users's key will always be self-signed, or at best signed by the user's own CA. How would the user be able to have it signed by any key in the builtin or secondary keyrings, without compiling the kernel with her own key?

(Side note, off-topic: I also fail to understand why the kernel doesn't accept pre-boot keys for signing modules. In the past it was possible to have hardware vendor keys (such in Dell) in the EFI db and use them for verifying vendor-provided 3rd party modules. Which was not a bad idea, IMHO. I sounds hypocritical to me not to trust the db keys. If those were compromised, the entire enviroment the kernel was running in would be compromised already).

> So, currently the .machine keyring is NOT useful for loading a MOK-signed
> kernel module. I think all MOKs will be loaded to .platform keyring. Unless
> Eric Snowberg's MOK CA patch be accepted:

Not sure what that patch would change in this respect, except placing additional restrictions on the keys that would be accepted.

Can you explain how the CA restriction is supposed to work (assuming the issue above is fixed somehow) ? Only CA certs from the MoK will be added to the machine and secondary keyrings. But how will the user sign the modules then? In the strictest form, the CA certs are not permitted to have the "digitalSigature" usage flag set. Thus AFAIK they can't be used to sign kernel modules. An intermediate cert would be needed which would be signed by the CA, and then used to sign the modules. But how would that intermediate cert be loaded into the kernel? IIUC it would end up in the .platform keyring which is _not_ used to verify modules...

> Kernel will check the existence of MokListTrustedRT. So we need to run
> "mokutil --trust-mok", otherwise all MOK will go to .platform keyring.

This seems weird to me too. Why would a user put a key in the MoK if she didn't want the kernel to trust it? It just adds extra inconvenience (having to run "mokutil --trust-mok"), but zero extra security, AFAICT.
Comment 16 Martin Wilck 2023-03-08 17:56:16 UTC
(In reply to Martin Wilck from comment #15)
> (In reply to Joey Lee from comment #9)

> > Base on v6.2 kernel, keys in .machine keyring still must be trusted(signed)
> > by key in built-in/secondary keyring. It applies restrict_link_to_ima and
> > depends on CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY.
> 
> [...]
> 
> So keys could be added from the machine keyring to the secondary keyring
> without being trusted by the secondary keyring beforehand, but such keys
> could never have been added to the machine keyring in the first place.
> 
> That looks like an upstream bug to me.

Sorry, no. I was wrong.

https://elixir.bootlin.com/linux/v6.2/source/security/integrity/digsig.c#L134
shows that there is no restriction at all for keys in the machine and platform key rings.

But now I fail to see why MoK keys don't make it into the secondary keyring...
Comment 17 Jiri Slaby 2023-03-09 06:07:36 UTC
(In reply to Stefan Dirsch from comment #14)
> > But we will need to change the rpm scripts of Nvidia driver again when Eric
> > Snowberg's patch set be merged on mainline if we want to follow upstream's
> > approach.
> 
> Ok. But I need to know in which way. And I would like to have the time to
> prepare this beforehand ...

Ok, this is enough.

commit 44ca817f15b215421a4c788790dd5351c186d1df (HEAD -> stable, origin/users/jslaby/stable/for-next)
Author: Jiri Slaby <jslaby@suse.cz>
Date:   Thu Mar 9 07:01:29 2023 +0100

    Disable lockdown. (bsc#1209006)
    
    This somehow doesn't play good wrt to external modules.
    
    When all is ready again, we can revert this revert.


master still have the patchset enabled, we can tune there...
Comment 18 Joey Lee 2023-03-09 09:02:17 UTC
Hi Martin,

(In reply to Martin Wilck from comment #16)
> (In reply to Martin Wilck from comment #15)
> > (In reply to Joey Lee from comment #9)
> 
> > > Base on v6.2 kernel, keys in .machine keyring still must be trusted(signed)
> > > by key in built-in/secondary keyring. It applies restrict_link_to_ima and
> > > depends on CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY.
> > 
> > [...]
> > 
> > So keys could be added from the machine keyring to the secondary keyring
> > without being trusted by the secondary keyring beforehand, but such keys
> > could never have been added to the machine keyring in the first place.
> > 
> > That looks like an upstream bug to me.
> 
> Sorry, no. I was wrong.
> 
> https://elixir.bootlin.com/linux/v6.2/source/security/integrity/digsig.c#L134
> shows that there is no restriction at all for keys in the machine and
> platform key rings.
> 
> But now I fail to see why MoK keys don't make it into the secondary
> keyring...

You are right! I missed the above code when tracing. I have tested .machine keyring and confirmed that .machine keyring be linked to .secondary keyring and can be used to verify kernel module.

First we need run "mokutil --trust-mok" command to request shim to create MokListTrustedRT for linking .machine keyring to .secondary keying.

Unfortunately we need shim-15.5 to support MokListTrustedRT, but we only have Microsoft signed shim-15.4 now. Our shim-15.6 and shim 15.7 is waiting shim usptream review and Microsoft signing. 

If anyone wants to try shim-15.7, it is in openSUSE:Factory:secure-boot repo:

https://build.opensuse.org/package/show/openSUSE:Factory:secure-boot/shim

You will need to enroll openSUSE CA or signkey to UEFI db. Then you can play shim-15.7.

After shim created MokListTrustedRT and boot success, keyctl shows:

Vigor135:~ # keyctl list %:.platform
6 keys in keyring:
1067995450: ---lswrv     0     0 asymmetric: Microsoft Windows Production PCA 2011: a92902398e16c49778cd90f99e4f9ae17c55af53
 22887073: ---lswrv     0     0 asymmetric: Build time autogenerated kernel key: fc6de3c630f48b63df52f138903ce4d57b4912cf
261332100: ---lswrv     0     0 asymmetric: Build time autogenerated kernel key: ec9a8cdfe96d577ab849ff3e58ee0d84b17d9745
174403700: ---lswrv     0     0 asymmetric: Build time autogenerated kernel key: e9454afc180d18db2c0311d43f6fe8dd65cb96e8
690509329: ---lswrv     0     0 asymmetric: Build time autogenerated kernel key: af96d2c6c40d1afc8b175658d0536fe4514e7501
351948099: ---lswrv     0     0 asymmetric: Microsoft Corporation UEFI CA 2011: 13adbf4309bd82709c8cd54f316ed522988a1bd4

Vigor135:~ # keyctl list %:.machine 
6 keys in keyring:
531558656: ---lswrv     0     0 asymmetric: openSUSE Secure Boot CA: 6842600de22c4c477e95be23dfea9513e5971762
905231616: ---lswrv     0     0 asymmetric: openSUSE Secure Boot Signkey: fd9f2c12e599d67cc7f9067541adf426b712469e  
   113219: ---lswrv     0     0 asymmetric: Kernel OBS Project: 1fb41512acbc8eebdf828d877e4367bf6c719af3
772042873: ---lswrv     0     0 asymmetric: Build time autogenerated kernel key: 959b5e1b135628040e10b510443790b327f6615d 
529014248: ---lswrv     0     0 asymmetric: Build time autogenerated kernel key: 55f24d5835fbedf68734252328b769eb29ddfe97
775007952: ---lswrv     0     0 asymmetric: Build time autogenerated kernel key: e9454afc180d18db2c0311d43f6fe8dd65cb96e8

So, all keys in mok unconditionally be added to .machine keyring. And keyring be linked to .secondary keyring:

Vigor135:~ # keyctl list %:.secondary_trusted_keys
2 keys in keyring:
236292887: ---lswrv     0     0 keyring: .builtin_trusted_keys
900602128: ---lswrv     0     0 keyring: .machine 

I have boot to self-built kernel and loaded a openSUSE signkey signed module success. So, I want to fix my comment#9, the .machine keyring works to verify kernel module. 

The problem is that we need Microsoft signs back openSUSE shim-15.6 or shim-15.7. Otherwise we still need downstream patch KEYS-Make-use-of-platform-keyring-for-module-signatu.patch.
Comment 19 Michal Suchanek 2023-03-09 09:24:32 UTC
(In reply to Joey Lee from comment #18)
> Hi Martin,
> 
> (In reply to Martin Wilck from comment #16)
> > (In reply to Martin Wilck from comment #15)
> > > (In reply to Joey Lee from comment #9)
> > 
> > > > Base on v6.2 kernel, keys in .machine keyring still must be trusted(signed)
> > > > by key in built-in/secondary keyring. It applies restrict_link_to_ima and
> > > > depends on CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY.
> > > 
> > > [...]
> > > 
> > > So keys could be added from the machine keyring to the secondary keyring
> > > without being trusted by the secondary keyring beforehand, but such keys
> > > could never have been added to the machine keyring in the first place.
> > > 
> > > That looks like an upstream bug to me.
> > 
> > Sorry, no. I was wrong.
> > 
> > https://elixir.bootlin.com/linux/v6.2/source/security/integrity/digsig.c#L134
> > shows that there is no restriction at all for keys in the machine and
> > platform key rings.
> > 
> > But now I fail to see why MoK keys don't make it into the secondary
> > keyring...
> 
> You are right! I missed the above code when tracing. I have tested .machine
> keyring and confirmed that .machine keyring be linked to .secondary keyring
> and can be used to verify kernel module.
> 
> First we need run "mokutil --trust-mok" command to request shim to create
> MokListTrustedRT for linking .machine keyring to .secondary keying.
> 
> Unfortunately we need shim-15.5 to support MokListTrustedRT, but we only
> have Microsoft signed shim-15.4 now. Our shim-15.6 and shim 15.7 is waiting
> shim usptream review and Microsoft signing. 

Or patch this requirement out of the kernel. What's the point anyway?

Or just verify everything with the platform keyring. It's trusted for kernel verification, anyway. Why that distinction?
Comment 20 Martin Wilck 2023-03-09 10:05:00 UTC
(In reply to Michal Suchanek from comment #19)

> Or just verify everything with the platform keyring. It's trusted for kernel
> verification, anyway. Why that distinction?

I agree. 

As noted above, I fail to understand what additional security upstream's MokListTrustedRT buys us. Repeating my previous question, why would anyone put keys into MoK which they don't trust? And while it's somewhat understandable that some people might not want to trust Microsoft's keys in the db (because of general contempt for Microsoft or what not), doing so doesn't provide any extra security, either. After all the firmware has already been verified by just these keys.
Comment 21 Joey Lee 2023-03-09 10:21:23 UTC
For reference, kernel upstream's plan of .platform and .machine keyrings is here:

keyrings, key usage, and trust models
https://lore.kernel.org/all/20220928055900.GT4909@linux-l9pv.suse/t/#m3ce7e451f1855d9c432965bb896cb7ce0f89e009

And, a PDF slides. Those pictures may be useful: 
https://static.sched.com/hosted_files/lssna2022/18/LSS%202022%20trust%20and%20keyrings.pdf

Newest patch set:
[PATCH v5 0/6] Add CA enforcement keyring restrictions
https://lore.kernel.org/lkml/20230302164652.83571-1-eric.snowberg@oracle.com/T/


Per my understood, "keys in UEFI db" only be trusted to verify booting/kexec. And MOKs also can be used to verify booting/kexec. CA MOKs can be used to verify keys for .ima keyring.
Comment 22 Michal Suchanek 2023-03-09 10:41:12 UTC
(In reply to Joey Lee from comment #21)
> For reference, kernel upstream's plan of .platform and .machine keyrings is
> here:
> 
> keyrings, key usage, and trust models
> https://lore.kernel.org/all/20220928055900.GT4909@linux-l9pv.suse/t/
> #m3ce7e451f1855d9c432965bb896cb7ce0f89e009

So there are only questions, no answers. It has been pointed out that the scheme proposed by upstream is inconsistent and broken, and there has been no reply. 

Upstream is not willing to concern itself with distribution kernel needs, and if we want to use MOK we need to patch the kernel downstream so that using MOK is possible.
Comment 23 Michal Suchanek 2023-03-09 10:51:07 UTC
I think that upstream as failing to understand that the transitivity of trust goes both ways.

If MS verifies SUSE shim, and SUSE shim accepts enrollment of Joe Users' key then MS transitively verifies enrollment of Joe Users' key. But if Joe User trusts SUSE shim with his key, and MS to verify that SUSE shim Joe User also transitively trusts that MS key.

You could enforce some baroque policies that only allow specific keys to be used for verification of specific things but the kernel does not have infrastructure for storing such key purpose information. Until such infrastructure exists key trust is just binary.
Comment 24 Martin Wilck 2023-03-09 11:18:56 UTC
From https://lore.kernel.org/all/20220928055900.GT4909@linux-l9pv.suse/t/#m3ce7e451f1855d9c432965bb896cb7ce0f89e009:

> The end-user will now need to enroll two keys. First the CA Key into the MOK and then the leaf cert into the secondary trusted keyring.

HOW would the user add this leaf cert? I am not getting it. From the PDF slides I got the impression that the "Root user" would play a role here, but I couldn't figure out how this would work, in particular how the root user's cert would be added to the kernel.

Wrt the general mind set, I agree with Michal.

IMO the biggest issue is that IMA is disabled as soon as a .machine keyring is populated. That looks like a political movement of upstream with the intention to deter people from using MoK (and thus, 3rd party modules).

Most of the main actors behind the current changes seem be IBM employees, plus the Oracle guy. I guess their intention is to find an upstream-accepted framework that would keep IMA functional while allowing a root of trust outside the kernel itself.
If they succeed without breaking the current, _relatively_ easy-to-use way to combine 3rd party modules with distro kernels, we might be able to drop our downstream patches, which would be a good thing. But AFAICS their approach would be harder to use, unless some additonal tooling is invented or incorporated in mokutil. MokListTrustedRT ist just an annoyance.
Comment 25 Stefan Dirsch 2023-03-09 12:03:53 UTC
Now that we reverted the lockdown patches, I think we can reassign this to Joey, so he can work on this ...

I will be happy to give a test kernel a try with my nvidia KMPs once things are implemented. :-)
Comment 26 Michal Suchanek 2023-03-09 12:12:58 UTC
(In reply to Martin Wilck from comment #24)
> From
> https://lore.kernel.org/all/20220928055900.GT4909@linux-l9pv.suse/t/
> #m3ce7e451f1855d9c432965bb896cb7ce0f89e009:
> 
> > The end-user will now need to enroll two keys. First the CA Key into the MOK and then the leaf cert into the secondary trusted keyring.
> 
> HOW would the user add this leaf cert? I am not getting it. From the PDF

At runtime, presumably with keyctl. This is not used in (open)SUSE at all but should be so that you can load official KMPs when running non-official kernel.
Comment 27 Martin Wilck 2023-03-09 18:21:15 UTC
So dracut would need to support loading such keys with keyctl from the initrd before any modules can be loaded?
Comment 28 Michal Suchanek 2023-03-09 18:31:19 UTC
If you need those modules loaded in ramdisk then yes.

Then again loading the keys is not done at all. Presumably whatever looks up and loads the key on the system could be packed into ramdisk as well if such tool existed.
Comment 29 Joey Lee 2023-03-13 06:04:24 UTC
(In reply to Jiri Slaby from comment #17)
> (In reply to Stefan Dirsch from comment #14)
> > > But we will need to change the rpm scripts of Nvidia driver again when Eric
> > > Snowberg's patch set be merged on mainline if we want to follow upstream's
> > > approach.
> > 
> > Ok. But I need to know in which way. And I would like to have the time to
> > prepare this beforehand ...
> 
> Ok, this is enough.
> 
> commit 44ca817f15b215421a4c788790dd5351c186d1df (HEAD -> stable,
> origin/users/jslaby/stable/for-next)
> Author: Jiri Slaby <jslaby@suse.cz>
> Date:   Thu Mar 9 07:01:29 2023 +0100
> 
>     Disable lockdown. (bsc#1209006)
>     
>     This somehow doesn't play good wrt to external modules.
>     
>     When all is ready again, we can revert this revert.
> 
> 
> master still have the patchset enabled, we can tune there...

I have sent new change to master/for-next.

I port the KEYS-Make-use-of-platform-keyring-for-module-signatu.patch patch, and also set CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT=y to detect secure boot.
Comment 30 Joey Lee 2023-03-14 13:27:50 UTC
(In reply to Martin Wilck from comment #24)
> From
> https://lore.kernel.org/all/20220928055900.GT4909@linux-l9pv.suse/t/
> #m3ce7e451f1855d9c432965bb896cb7ce0f89e009:
> 
> > The end-user will now need to enroll two keys. First the CA Key into the MOK and then the leaf cert into the secondary trusted keyring.
> 
> HOW would the user add this leaf cert? I am not getting it. From the PDF
> slides I got the impression that the "Root user" would play a role here, but
> I couldn't figure out how this would work, in particular how the root user's
> cert would be added to the kernel.

As Michal mentioned, using keyctl. And using keyctl with dracut in initrd to add leaf cert to .ima/.evm or even .secondary_trusted_keys. 

> 
> Wrt the general mind set, I agree with Michal.
> 

I agree that the upstream solution is complex, and I do not fully understood the Imputed or Transitive concept in their theory. But I think that those certificates in db/mok must be differentiated based on functionality purpose. The trust is not spread from a purpose to other purposes.

Using usage extension in certificates to separate different purposes is a strategy. IMA maintainer uses CA in BasicConstraints, digitalSignature and keyCertSign to identify CA MOK. And NIAP PPOS certification uses codeSign extend key usage. 

> IMO the biggest issue is that IMA is disabled as soon as a .machine keyring
> is populated. That looks like a political movement of upstream with the
> intention to deter people from using MoK (and thus, 3rd party modules).
> 

I have applied Eric Snowberg's patch set on v6.2 kernel and tested. I used the following kernel config, and I got a kernel behavior that is similar with our downstream patch for modsign:

CONFIG_INTEGRITY_MACHINE_KEYRING=y        <-- enable .machine keyring
CONFIG_INTEGRITY_CA_MACHINE_KEYRING=n     <-- allow all MOK add to .machine
COFNIG_INTEGRITY_TRUSTED_KEYRING=y        <-- enable .ima/.evm
CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY=y    <-- .secondary keyring trusted key can be added to .ima/.evm

Enable MokListTrustedRT, looks that the MokListTrusted be set by default after shim 15.6:

commit 2670c6a17edb239949152c471445fc533d8525aa
Author: Eric Snowberg <eric.snowberg@oracle.com>
Date:   Thu Feb 17 18:29:58 2022 -0500

    Allow MokListTrusted to be enabled by default

Using keyctl tool shows .secondary_trusted_keys and .machine keyrings, confirmed that MOKs are added and linked:

Vigor135:~ # keyctl list %:.secondary_trusted_keys
2 keys in keyring:
727581285: ---lswrv     0     0 keyring: .builtin_trusted_keys
978122164: ---lswrv     0     0 keyring: .machine       <-- .machine linked 

Vigor135:~ # keyctl list %:.machine
7 keys in keyring:
661930310: ---lswrv     0     0 asymmetric: openSUSE Secure Boot CA: 6842600de22c4c477e95be23dfea9513e5971762
 46964368: ---lswrv     0     0 asymmetric: openSUSE Secure Boot Signkey: fd9f2c12e599d67cc7f9067541adf426b712469e
119545939: ---lswrv     0     0 asymmetric: Build time autogenerated kernel key11111: 92705a4f4be67f7a90a52166573dd590711f9e32
366702073: ---lswrv     0     0 asymmetric: Kernel OBS Project: 1fb41512acbc8eebdf828d877e4367bf6c719af3
392485614: ---lswrv     0     0 asymmetric: Build time autogenerated kernel key: 959b5e1b135628040e10b510443790b327f6615d
820273393: ---lswrv     0     0 asymmetric: Build time autogenerated kernel key: 55f24d5835fbedf68734252328b769eb29ddfe97
1055853409: ---lswrv     0     0 asymmetric: Build time autogenerated kernel key: e9454afc180d18db2c0311d43f6fe8dd65cb96e8


For kernel module sign:
No difference with our downstream patch, all MOKs be add to .machine keyring and link to .secondary_trusted_keys. So all MOKs can be used to verify kernel modules.

For .ima/.evm
All MOKs can be used to verify keys that will go to .ima/.evm keyrings.
Comment 31 Michal Suchanek 2023-03-14 13:47:03 UTC
(In reply to Joey Lee from comment #30)

> I agree that the upstream solution is complex, and I do not fully understood
> the Imputed or Transitive concept in their theory. But I think that those
> certificates in db/mok must be differentiated based on functionality
> purpose. The trust is not spread from a purpose to other purposes.

And the x509 has purpose flags but the kernel trashes all of them except the CA flag. If it wants to differentiate purposes it needs to store those purpose flags.

> 
> Using usage extension in certificates to separate different purposes is a
> strategy. IMA maintainer uses CA in BasicConstraints, digitalSignature and
> keyCertSign to identify CA MOK. And NIAP PPOS certification uses codeSign
> extend key usage. 

Which applies to both kexec and module loading, these are both code. Loaded into the same security context even. Yet kernel upstream inexplicably insists on using different keys for these making their scheme unusable for us.

If it wants to differentiate kexec and module loading, or modules by different vendors it needs to invent new extension for that. Until such certificate extension exists both kernel and modules are code.
Comment 32 Martin Wilck 2023-03-14 14:25:33 UTC
(In reply to Joey Lee from comment #30)

> I agree that the upstream solution is complex, and I do not fully understood
> the Imputed or Transitive concept in their theory. But I think that those
> certificates in db/mok must be differentiated based on functionality
> purpose. The trust is not spread from a purpose to other purposes.

I agree. Especially the distinction between CA keys and code-signing keys and other "low-level" purposes makes sense (although AFAIK the main reason for making the distinction is that it allows the certificates lower in the chain to be invalidated while the CA remains intact).

But I still hold that it the db certificates aren't trusted, you can't trust anything in the system. A malware-infected firmware could have injected false certs, keys, and checksums into the kernel before it even starts. Intel TXT had that concept of a "dynamic root of trust", but TXT wasn't successful, so we're left with the static root of trust, which is the UEFI db, like it or not.

Or am I missing something? Do modern TPMs provide us with a way to create a trust relationship which doesn't depend on trusting the firmware?
 
> Using usage extension in certificates to separate different purposes is a
> strategy. IMA maintainer uses CA in BasicConstraints, digitalSignature and
> keyCertSign to identify CA MOK. And NIAP PPOS certification uses codeSign
> extend key usage. 

That makes sense. But it does not make sense to me that only the CA certs can be loaded into the machine keyring. Normally you provide the full chain of certificates that's necessary to verify any given signature. And the full chain in our case would comprise the code-signing certs as well.

> I have applied Eric Snowberg's patch set on v6.2 kernel and tested. I used
> the following kernel config, and I got a kernel behavior that is similar
> with our downstream patch for modsign:
> 
> ...
> 
> For kernel module sign:
> No difference with our downstream patch, all MOKs be add to .machine keyring
> and link to .secondary_trusted_keys. So all MOKs can be used to verify
> kernel modules.
> 
> For .ima/.evm
> All MOKs can be used to verify keys that will go to .ima/.evm keyrings.

That sounds good. So we could actually use this setup, at least as long as upstream doesn't enforce CONFIG_INTEGRITY_CA_MACHINE_KEYRING=y.

That said, I still fail to understand what MokListTrustedRT is good for. And if we "enable it by default", we might as well just shred it, no?
Comment 33 Joey Lee 2023-03-24 15:30:59 UTC
(In reply to Michal Suchanek from comment #31)
> (In reply to Joey Lee from comment #30)
> 
> > I agree that the upstream solution is complex, and I do not fully understood
> > the Imputed or Transitive concept in their theory. But I think that those
> > certificates in db/mok must be differentiated based on functionality
> > purpose. The trust is not spread from a purpose to other purposes.
> 
> And the x509 has purpose flags but the kernel trashes all of them except the
> CA flag. If it wants to differentiate purposes it needs to store those
> purpose flags.
> 

In the digsig-restrictions branch in Eric Snowberg's git, looks that he is working on add restriction of digitalSignature and codeSigning EKU to MOK:

https://github.com/esnowberg/linux/commits/digsig-restrictions

But, looks that those restriction are only for CONFIG_INTEGRITY_CA_MACHINE_KEYRING=y. Our plan is CONFIG_INTEGRITY_CA_MACHINE_KEYRING=n.

I will find time to test it.

> > 
> > Using usage extension in certificates to separate different purposes is a
> > strategy. IMA maintainer uses CA in BasicConstraints, digitalSignature and
> > keyCertSign to identify CA MOK. And NIAP PPOS certification uses codeSign
> > extend key usage. 
> 
> Which applies to both kexec and module loading, these are both code. Loaded
> into the same security context even. Yet kernel upstream inexplicably
> insists on using different keys for these making their scheme unusable for
> us.
> 
> If it wants to differentiate kexec and module loading, or modules by
> different vendors it needs to invent new extension for that. Until such
> certificate extension exists both kernel and modules are code.

The kexec can use .secondary and .platform keyring. And modsign can use .secondary keyring. Base on my testing on comment#30, when CONFIG_INTEGRITY_CA_MACHINE_KEYRING=n, all mok can be used to verify kernel module.

Upstream's solution is adding more restrictions when using mok with .ima/.evm. And those restrictions can be turn-off.