mbox series

[v8,00/17] Enroll kernel keys thru MOK

Message ID 20211124044124.998170-1-eric.snowberg@oracle.com
Headers show
Series Enroll kernel keys thru MOK | expand

Message

Eric Snowberg Nov. 24, 2021, 4:41 a.m. UTC
Back in 2013 Linus requested a feature to allow end-users to have the 
ability "to add their own keys and sign modules they trust". This was
his *second* order outlined here [1]. There have been many attempts 
over the years to solve this problem, all have been rejected.  Many 
of the failed attempts loaded all preboot firmware keys into the kernel,
including the Secure Boot keys. Many distributions carry one of these 
rejected attempts [2], [3], [4]. This series tries to solve this problem 
with a solution that takes into account all the problems brought up in 
the previous attempts.

On UEFI based systems, this series introduces a new Linux kernel keyring 
containing the Machine Owner Keys (MOK) called machine. It also defines
a new MOK variable in shim. This variable allows the end-user to decide 
if they want to load MOK keys into the machine keyring. Mimi has suggested 
that only CA keys contained within the MOK be loaded into the machine 
keyring. All other certs will load into the platform keyring instead.

By default, nothing changes; MOK keys are not loaded into the machine
keyring.  They are only loaded after the end-user makes the decision 
themselves.  The end-user would set this through mokutil using a new 
--trust-mok option [5]. This would work similar to how the kernel uses 
MOK variables to enable/disable signature validation as well as use/ignore 
the db. Any kernel operation that uses either the builtin or secondary 
trusted keys as a trust source shall also reference the new machine 
keyring as a trust source.

Secure Boot keys will never be loaded into the machine keyring.  They
will always be loaded into the platform keyring.  If an end-user wanted 
to load one, they would need to enroll it into the MOK.

Steps required by the end user:

Sign kernel module with user created key:
$ /usr/src/kernels/$(uname -r)/scripts/sign-file sha512 \
   machine_signing_key.priv machine_signing_key.x509 my_module.ko

Import the key into the MOK
$ mokutil --import machine_signing_key.x509

Setup the kernel to load MOK keys into the .machine keyring
$ mokutil --trust-mok

Then reboot, the MokManager will load and ask if you want to trust the
MOK key and enroll the MOK into the MOKList.  Afterwards the signed kernel
module will load.

I have included  a link to the mokutil [5] changes I have made to support 
this new functionality.  The shim changes have now been accepted
upstream [6].

Upstream shim is located here [7], the build instructions are here [8].
TLDR:

$ git clone --recurse-submodules https://github.com/rhboot/shim
$ cd shim
$ make

After building shim, move shimx64.efi and mmx64.efi to the vendor or 
distribution specific directory on your EFI System Partition (assuming
you are building on x86). The instructions above are the minimal
steps needed to build shim to test this feature. It is assumed
Secure Boot shall not be enabled for this testing. To do testing
with Secure Boot enabled, all steps in the build instructions [8]
must be followed.

Instructions for building mokutil (including the new changes):

$ git clone -b mokvars-v3 https://github.com/esnowberg/mokutil.git
$ cd mokutil/
$ ./autogen.sh
$ make

[1] https://marc.info/?l=linux-kernel&m=136185386310140&w=2
[2] https://lore.kernel.org/lkml/1479737095.2487.34.camel@linux.vnet.ibm.com/
[3] https://lore.kernel.org/lkml/1556221605.24945.3.camel@HansenPartnership.com/
[4] https://lore.kernel.org/linux-integrity/1e41f22b1f11784f1e943f32bf62034d4e054cdb.camel@HansenPartnership.com/
[5] https://github.com/esnowberg/mokutil/tree/mokvars-v3
[6] https://github.com/rhboot/shim/commit/4e513405b4f1641710115780d19dcec130c5208f
[7] https://github.com/rhboot/shim
[8] https://github.com/rhboot/shim/blob/main/BUILDING


Eric Snowberg (17):
  KEYS: Create static version of public_key_verify_signature
  integrity: Fix warning about missing prototypes
  integrity: Introduce a Linux keyring called machine
  integrity: Do not allow machine keyring updates following init
  X.509: Parse Basic Constraints for CA
  KEYS: CA link restriction
  integrity: restrict INTEGRITY_KEYRING_MACHINE to restrict_link_by_ca
  integrity: add new keyring handler for mok keys
  KEYS: Rename get_builtin_and_secondary_restriction
  KEYS: add a reference to machine keyring
  KEYS: Introduce link restriction for machine keys
  KEYS: integrity: change link restriction to trust the machine keyring
  integrity: store reference to machine keyring
  KEYS: link machine trusted keys to secondary_trusted_keys
  efi/mokvar: move up init order
  integrity: Trust MOK keys if MokListTrustedRT found
  integrity: Only use machine keyring when uefi_check_trust_mok_keys is
    true

 certs/system_keyring.c                        | 48 +++++++++++-
 crypto/asymmetric_keys/restrict.c             | 43 +++++++++++
 crypto/asymmetric_keys/x509_cert_parser.c     |  9 +++
 drivers/firmware/efi/mokvar-table.c           |  2 +-
 include/crypto/public_key.h                   | 25 ++++++
 include/keys/system_keyring.h                 | 14 ++++
 security/integrity/Kconfig                    | 12 +++
 security/integrity/Makefile                   |  1 +
 security/integrity/digsig.c                   | 23 +++++-
 security/integrity/integrity.h                | 17 +++-
 .../platform_certs/keyring_handler.c          | 18 ++++-
 .../platform_certs/keyring_handler.h          |  5 ++
 security/integrity/platform_certs/load_uefi.c |  4 +-
 .../platform_certs/machine_keyring.c          | 77 +++++++++++++++++++
 14 files changed, 287 insertions(+), 11 deletions(-)
 create mode 100644 security/integrity/platform_certs/machine_keyring.c


base-commit: 136057256686de39cc3a07c2e39ef6bc43003ff6

Comments

Jarkko Sakkinen Nov. 27, 2021, 12:43 a.m. UTC | #1
On Tue, 2021-11-23 at 23:41 -0500, Eric Snowberg wrote:
> Parse the X.509 Basic Constraints.  The basic constraints extension
> identifies whether the subject of the certificate is a CA.
> 
> BasicConstraints ::= SEQUENCE {
>         cA                      BOOLEAN DEFAULT FALSE,
>         pathLenConstraint       INTEGER (0..MAX) OPTIONAL }
> 
> If the CA is true, store it in a new public_key field call key_is_ca.
> This will be used in a follow on patch that requires knowing if the
> public key is a CA.
> 
> Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>

You could extend the description to state why kernel needs X.509 Basic
Constraints support.

/Jarkko

> ---
> v7: Initial version
> v8: Moved key_is_ca after key_is_private, recommended by Mimi
> ---
>  crypto/asymmetric_keys/x509_cert_parser.c | 9 +++++++++
>  include/crypto/public_key.h               | 1 +
>  2 files changed, 10 insertions(+)
> 
> diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
> index 6d003096b5bc..f4299b8a4926 100644
> --- a/crypto/asymmetric_keys/x509_cert_parser.c
> +++ b/crypto/asymmetric_keys/x509_cert_parser.c
> @@ -571,6 +571,15 @@ int x509_process_extension(void *context, size_t hdrlen,
>                 return 0;
>         }
>  
> +       if (ctx->last_oid == OID_basicConstraints) {
> +               if (v[0] != (ASN1_CONS_BIT | ASN1_SEQ))
> +                       return -EBADMSG;
> +               if (v[1] != vlen - 2)
> +                       return -EBADMSG;
> +               if (v[1] != 0 && v[2] == ASN1_BOOL && v[3] == 1)
> +                       ctx->cert->pub->key_is_ca = true;
> +       }
> +
>         return 0;
>  }
>  
> diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
> index a9b2e600b7cc..72dcbc06ef9c 100644
> --- a/include/crypto/public_key.h
> +++ b/include/crypto/public_key.h
> @@ -26,6 +26,7 @@ struct public_key {
>         void *params;
>         u32 paramlen;
>         bool key_is_private;
> +       bool key_is_ca;
>         const char *id_type;
>         const char *pkey_algo;
>  };
Eric Snowberg Nov. 30, 2021, 5:21 p.m. UTC | #2
> On Nov 26, 2021, at 5:49 PM, Jarkko Sakkinen <jarkko@kernel.org> wrote:
> 
> On Tue, 2021-11-23 at 23:41 -0500, Eric Snowberg wrote:
>> In preparation for returning either the existing
>> restrict_link_by_builtin_and_secondary_trusted or the upcoming
>> restriction that includes the trusted builtin, secondary and
>> machine keys, to improve clarity, rename
>> get_builtin_and_secondary_restriction to get_secondary_restriction.
>> 
>> Suggested-by: Mimi Zohar <zohar@linux.ibm.com>
>> Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>
>> Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
>> ---
>> v6: Initial version
>> v7: Unmodified from v7
>> v8: Code unmodified from v7, added Mimi's Reviewed-by
>> ---
>>  certs/system_keyring.c | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-)
>> 
>> diff --git a/certs/system_keyring.c b/certs/system_keyring.c
>> index 692365dee2bd..8f1f87579819 100644
>> --- a/certs/system_keyring.c
>> +++ b/certs/system_keyring.c
>> @@ -77,7 +77,7 @@ int restrict_link_by_builtin_and_secondary_trusted(
>>   * Allocate a struct key_restriction for the "builtin and secondary trust"
>>   * keyring. Only for use in system_trusted_keyring_init().
>>   */
>> -static __init struct key_restriction *get_builtin_and_secondary_restriction(void)
>> +static __init struct key_restriction *get_secondary_restriction(void)
>>  {
>>         struct key_restriction *restriction;
>>  
>> @@ -117,7 +117,7 @@ static __init int system_trusted_keyring_init(void)
>>                                KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH |
>>                                KEY_USR_WRITE),
>>                               KEY_ALLOC_NOT_IN_QUOTA,
>> -                             get_builtin_and_secondary_restriction(),
>> +                             get_secondary_restriction(),
>>                               NULL);
>>         if (IS_ERR(secondary_trusted_keys))
>>                 panic("Can't allocate secondary trusted keyring\n");
> 
> This is wrong order.
> 
> You should first do the changes that make the old name
> obsolete and only after that have a patch that does the
> rename. Unfortunately, this patch cannot possibly acked
> with the current order.

I can change the order, but I'm confused how this would work for a git bisect. 
If the rename happens afterwards, now two patches will always need to be 
reverted instead of the possibility of one.  Is this your expectation?
Jarkko Sakkinen Dec. 1, 2021, 10:27 a.m. UTC | #3
On Tue, Nov 30, 2021 at 05:21:45PM +0000, Eric Snowberg wrote:
> 
> 
> > On Nov 26, 2021, at 5:49 PM, Jarkko Sakkinen <jarkko@kernel.org> wrote:
> > 
> > On Tue, 2021-11-23 at 23:41 -0500, Eric Snowberg wrote:
> >> In preparation for returning either the existing
> >> restrict_link_by_builtin_and_secondary_trusted or the upcoming
> >> restriction that includes the trusted builtin, secondary and
> >> machine keys, to improve clarity, rename
> >> get_builtin_and_secondary_restriction to get_secondary_restriction.
> >> 
> >> Suggested-by: Mimi Zohar <zohar@linux.ibm.com>
> >> Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>
> >> Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
> >> ---
> >> v6: Initial version
> >> v7: Unmodified from v7
> >> v8: Code unmodified from v7, added Mimi's Reviewed-by
> >> ---
> >>  certs/system_keyring.c | 4 ++--
> >>  1 file changed, 2 insertions(+), 2 deletions(-)
> >> 
> >> diff --git a/certs/system_keyring.c b/certs/system_keyring.c
> >> index 692365dee2bd..8f1f87579819 100644
> >> --- a/certs/system_keyring.c
> >> +++ b/certs/system_keyring.c
> >> @@ -77,7 +77,7 @@ int restrict_link_by_builtin_and_secondary_trusted(
> >>   * Allocate a struct key_restriction for the "builtin and secondary trust"
> >>   * keyring. Only for use in system_trusted_keyring_init().
> >>   */
> >> -static __init struct key_restriction *get_builtin_and_secondary_restriction(void)
> >> +static __init struct key_restriction *get_secondary_restriction(void)
> >>  {
> >>         struct key_restriction *restriction;
> >>  
> >> @@ -117,7 +117,7 @@ static __init int system_trusted_keyring_init(void)
> >>                                KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH |
> >>                                KEY_USR_WRITE),
> >>                               KEY_ALLOC_NOT_IN_QUOTA,
> >> -                             get_builtin_and_secondary_restriction(),
> >> +                             get_secondary_restriction(),
> >>                               NULL);
> >>         if (IS_ERR(secondary_trusted_keys))
> >>                 panic("Can't allocate secondary trusted keyring\n");
> > 
> > This is wrong order.
> > 
> > You should first do the changes that make the old name
> > obsolete and only after that have a patch that does the
> > rename. Unfortunately, this patch cannot possibly acked
> > with the current order.
> 
> I can change the order, but I'm confused how this would work for a git bisect. 
> If the rename happens afterwards, now two patches will always need to be 
> reverted instead of the possibility of one.  Is this your expectation?

I'd drop this patch altogether. Old name is a bit ugly but does it matter
all that much?

You already 16 patches without this.

/Jarkko
Mimi Zohar Dec. 1, 2021, 1:46 p.m. UTC | #4
On Wed, 2021-12-01 at 12:27 +0200, Jarkko Sakkinen wrote:
> On Tue, Nov 30, 2021 at 05:21:45PM +0000, Eric Snowberg wrote:
> > 
> > 
> > > On Nov 26, 2021, at 5:49 PM, Jarkko Sakkinen <jarkko@kernel.org> wrote:
> > > 
> > > On Tue, 2021-11-23 at 23:41 -0500, Eric Snowberg wrote:
> > >> In preparation for returning either the existing
> > >> restrict_link_by_builtin_and_secondary_trusted or the upcoming
> > >> restriction that includes the trusted builtin, secondary and
> > >> machine keys, to improve clarity, rename
> > >> get_builtin_and_secondary_restriction to get_secondary_restriction.
> > >> 
> > >> Suggested-by: Mimi Zohar <zohar@linux.ibm.com>
> > >> Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>
> > >> Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
> > >> ---
> > >> v6: Initial version
> > >> v7: Unmodified from v7
> > >> v8: Code unmodified from v7, added Mimi's Reviewed-by
> > >> ---
> > >>  certs/system_keyring.c | 4 ++--
> > >>  1 file changed, 2 insertions(+), 2 deletions(-)
> > >> 
> > >> diff --git a/certs/system_keyring.c b/certs/system_keyring.c
> > >> index 692365dee2bd..8f1f87579819 100644
> > >> --- a/certs/system_keyring.c
> > >> +++ b/certs/system_keyring.c
> > >> @@ -77,7 +77,7 @@ int restrict_link_by_builtin_and_secondary_trusted(
> > >>   * Allocate a struct key_restriction for the "builtin and secondary trust"
> > >>   * keyring. Only for use in system_trusted_keyring_init().
> > >>   */
> > >> -static __init struct key_restriction *get_builtin_and_secondary_restriction(void)
> > >> +static __init struct key_restriction *get_secondary_restriction(void)
> > >>  {
> > >>         struct key_restriction *restriction;
> > >>  
> > >> @@ -117,7 +117,7 @@ static __init int system_trusted_keyring_init(void)
> > >>                                KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH |
> > >>                                KEY_USR_WRITE),
> > >>                               KEY_ALLOC_NOT_IN_QUOTA,
> > >> -                             get_builtin_and_secondary_restriction(),
> > >> +                             get_secondary_restriction(),
> > >>                               NULL);
> > >>         if (IS_ERR(secondary_trusted_keys))
> > >>                 panic("Can't allocate secondary trusted keyring\n");
> > > 
> > > This is wrong order.
> > > 
> > > You should first do the changes that make the old name
> > > obsolete and only after that have a patch that does the
> > > rename. Unfortunately, this patch cannot possibly acked
> > > with the current order.
> >
> > I can change the order, but I'm confused how this would work for a git bisect. 
> > If the rename happens afterwards, now two patches will always need to be 
> > reverted instead of the possibility of one.  Is this your expectation?

If the keyring name change is independent of any other changes, as
Jarkko suggested, nothing would break.

> I'd drop this patch altogether. Old name is a bit ugly but does it matter
> all that much?

The name "get_builtin_and_secondary_restriction" implies trust based on
keys in the ".builtin_trusted_keys" and ".secondary_trusted_keys"
keyrings.  This patch set is extending that to include keys on the new
".machine" keyring, by linking it to the secondary keyring.  Is leaving
the name unchanged really an option?

> 
> You already 16 patches without this.

Agreed, it's a lot.  In the past, I've asked Eric to see if some of
them could be squashed.

Mimi
Jarkko Sakkinen Dec. 4, 2021, 5:39 p.m. UTC | #5
On Wed, Dec 01, 2021 at 08:46:53AM -0500, Mimi Zohar wrote:
> On Wed, 2021-12-01 at 12:27 +0200, Jarkko Sakkinen wrote:
> > On Tue, Nov 30, 2021 at 05:21:45PM +0000, Eric Snowberg wrote:
> > > 
> > > 
> > > > On Nov 26, 2021, at 5:49 PM, Jarkko Sakkinen <jarkko@kernel.org> wrote:
> > > > 
> > > > On Tue, 2021-11-23 at 23:41 -0500, Eric Snowberg wrote:
> > > >> In preparation for returning either the existing
> > > >> restrict_link_by_builtin_and_secondary_trusted or the upcoming
> > > >> restriction that includes the trusted builtin, secondary and
> > > >> machine keys, to improve clarity, rename
> > > >> get_builtin_and_secondary_restriction to get_secondary_restriction.
> > > >> 
> > > >> Suggested-by: Mimi Zohar <zohar@linux.ibm.com>
> > > >> Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>
> > > >> Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
> > > >> ---
> > > >> v6: Initial version
> > > >> v7: Unmodified from v7
> > > >> v8: Code unmodified from v7, added Mimi's Reviewed-by
> > > >> ---
> > > >>  certs/system_keyring.c | 4 ++--
> > > >>  1 file changed, 2 insertions(+), 2 deletions(-)
> > > >> 
> > > >> diff --git a/certs/system_keyring.c b/certs/system_keyring.c
> > > >> index 692365dee2bd..8f1f87579819 100644
> > > >> --- a/certs/system_keyring.c
> > > >> +++ b/certs/system_keyring.c
> > > >> @@ -77,7 +77,7 @@ int restrict_link_by_builtin_and_secondary_trusted(
> > > >>   * Allocate a struct key_restriction for the "builtin and secondary trust"
> > > >>   * keyring. Only for use in system_trusted_keyring_init().
> > > >>   */
> > > >> -static __init struct key_restriction *get_builtin_and_secondary_restriction(void)
> > > >> +static __init struct key_restriction *get_secondary_restriction(void)
> > > >>  {
> > > >>         struct key_restriction *restriction;
> > > >>  
> > > >> @@ -117,7 +117,7 @@ static __init int system_trusted_keyring_init(void)
> > > >>                                KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH |
> > > >>                                KEY_USR_WRITE),
> > > >>                               KEY_ALLOC_NOT_IN_QUOTA,
> > > >> -                             get_builtin_and_secondary_restriction(),
> > > >> +                             get_secondary_restriction(),
> > > >>                               NULL);
> > > >>         if (IS_ERR(secondary_trusted_keys))
> > > >>                 panic("Can't allocate secondary trusted keyring\n");
> > > > 
> > > > This is wrong order.
> > > > 
> > > > You should first do the changes that make the old name
> > > > obsolete and only after that have a patch that does the
> > > > rename. Unfortunately, this patch cannot possibly acked
> > > > with the current order.
> > >
> > > I can change the order, but I'm confused how this would work for a git bisect. 
> > > If the rename happens afterwards, now two patches will always need to be 
> > > reverted instead of the possibility of one.  Is this your expectation?
> 
> If the keyring name change is independent of any other changes, as
> Jarkko suggested, nothing would break.
> 
> > I'd drop this patch altogether. Old name is a bit ugly but does it matter
> > all that much?
> 
> The name "get_builtin_and_secondary_restriction" implies trust based on
> keys in the ".builtin_trusted_keys" and ".secondary_trusted_keys"
> keyrings.  This patch set is extending that to include keys on the new
> ".machine" keyring, by linking it to the secondary keyring.  Is leaving
> the name unchanged really an option?

Yes, it is an option, as long as it is documented correctly in the
prepending kdoc the symbol name does not matter all that much..

/Jarkko
Eric Snowberg Dec. 15, 2021, 6:14 p.m. UTC | #6
> On Dec 1, 2021, at 6:46 AM, Mimi Zohar <zohar@linux.ibm.com> wrote:
> 
> On Wed, 2021-12-01 at 12:27 +0200, Jarkko Sakkinen wrote:
>> On Tue, Nov 30, 2021 at 05:21:45PM +0000, Eric Snowberg wrote:
>>> 
>>> 
>>>> On Nov 26, 2021, at 5:49 PM, Jarkko Sakkinen <jarkko@kernel.org> wrote:
>>>> 
>>>> On Tue, 2021-11-23 at 23:41 -0500, Eric Snowberg wrote:
>>>>> In preparation for returning either the existing
>>>>> restrict_link_by_builtin_and_secondary_trusted or the upcoming
>>>>> restriction that includes the trusted builtin, secondary and
>>>>> machine keys, to improve clarity, rename
>>>>> get_builtin_and_secondary_restriction to get_secondary_restriction.
>>>>> 
>>>>> Suggested-by: Mimi Zohar <zohar@linux.ibm.com>
>>>>> Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>
>>>>> Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
>>>>> ---
>>>>> v6: Initial version
>>>>> v7: Unmodified from v7
>>>>> v8: Code unmodified from v7, added Mimi's Reviewed-by
>>>>> ---
>>>>> certs/system_keyring.c | 4 ++--
>>>>> 1 file changed, 2 insertions(+), 2 deletions(-)
>>>>> 
>>>>> diff --git a/certs/system_keyring.c b/certs/system_keyring.c
>>>>> index 692365dee2bd..8f1f87579819 100644
>>>>> --- a/certs/system_keyring.c
>>>>> +++ b/certs/system_keyring.c
>>>>> @@ -77,7 +77,7 @@ int restrict_link_by_builtin_and_secondary_trusted(
>>>>>  * Allocate a struct key_restriction for the "builtin and secondary trust"
>>>>>  * keyring. Only for use in system_trusted_keyring_init().
>>>>>  */
>>>>> -static __init struct key_restriction *get_builtin_and_secondary_restriction(void)
>>>>> +static __init struct key_restriction *get_secondary_restriction(void)
>>>>> {
>>>>>        struct key_restriction *restriction;
>>>>> 
>>>>> @@ -117,7 +117,7 @@ static __init int system_trusted_keyring_init(void)
>>>>>                               KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH |
>>>>>                               KEY_USR_WRITE),
>>>>>                              KEY_ALLOC_NOT_IN_QUOTA,
>>>>> -                             get_builtin_and_secondary_restriction(),
>>>>> +                             get_secondary_restriction(),
>>>>>                              NULL);
>>>>>        if (IS_ERR(secondary_trusted_keys))
>>>>>                panic("Can't allocate secondary trusted keyring\n");
>>>> 
>>>> This is wrong order.
>>>> 
>>>> You should first do the changes that make the old name
>>>> obsolete and only after that have a patch that does the
>>>> rename. Unfortunately, this patch cannot possibly acked
>>>> with the current order.
>>> 
>>> I can change the order, but I'm confused how this would work for a git bisect. 
>>> If the rename happens afterwards, now two patches will always need to be 
>>> reverted instead of the possibility of one.  Is this your expectation?
> 
> If the keyring name change is independent of any other changes, as
> Jarkko suggested, nothing would break.
> 
>> I'd drop this patch altogether. Old name is a bit ugly but does it matter
>> all that much?
> 
> The name "get_builtin_and_secondary_restriction" implies trust based on
> keys in the ".builtin_trusted_keys" and ".secondary_trusted_keys"
> keyrings.  This patch set is extending that to include keys on the new
> ".machine" keyring, by linking it to the secondary keyring.  Is leaving
> the name unchanged really an option?
> 
>> 
>> You already 16 patches without this.
> 
> Agreed, it's a lot.  In the past, I've asked Eric to see if some of
> them could be squashed.

The series grew based on requests added in each round.  How about
I drop IMA support from the next round?  This would eliminate nine patches
from the series (5, 6, 7, 9-14), leaving six patches to introduce and enable 
the new machine keyring (3, 4, 8, 15-17).  The first two patches could 
be taken today.  The only reason the first two are included is to get this series 
through the kernel test robot.

This would allow the machine keyring to be used for module signing.  Afterwards 
I could introduce the CA restriction behind another Kconfig in a different series to 
add back IMA support. Let me know if this would be a better approach.
Mimi Zohar Dec. 15, 2021, 7:54 p.m. UTC | #7
On Wed, 2021-12-15 at 18:14 +0000, Eric Snowberg wrote:
> 
> > On Dec 1, 2021, at 6:46 AM, Mimi Zohar <zohar@linux.ibm.com> wrote:
> > 
> > On Wed, 2021-12-01 at 12:27 +0200, Jarkko Sakkinen wrote:
> >> On Tue, Nov 30, 2021 at 05:21:45PM +0000, Eric Snowberg wrote:
> >>> 
> >>> 
> >>>> On Nov 26, 2021, at 5:49 PM, Jarkko Sakkinen <jarkko@kernel.org> wrote:
> >>>> 
> >>>> On Tue, 2021-11-23 at 23:41 -0500, Eric Snowberg wrote:
> >>>>> In preparation for returning either the existing
> >>>>> restrict_link_by_builtin_and_secondary_trusted or the upcoming
> >>>>> restriction that includes the trusted builtin, secondary and
> >>>>> machine keys, to improve clarity, rename
> >>>>> get_builtin_and_secondary_restriction to get_secondary_restriction.
> >>>>> 
> >>>>> Suggested-by: Mimi Zohar <zohar@linux.ibm.com>
> >>>>> Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>
> >>>>> Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
> >>>>> ---
> >>>>> v6: Initial version
> >>>>> v7: Unmodified from v7
> >>>>> v8: Code unmodified from v7, added Mimi's Reviewed-by
> >>>>> ---
> >>>>> certs/system_keyring.c | 4 ++--
> >>>>> 1 file changed, 2 insertions(+), 2 deletions(-)
> >>>>> 
> >>>>> diff --git a/certs/system_keyring.c b/certs/system_keyring.c
> >>>>> index 692365dee2bd..8f1f87579819 100644
> >>>>> --- a/certs/system_keyring.c
> >>>>> +++ b/certs/system_keyring.c
> >>>>> @@ -77,7 +77,7 @@ int restrict_link_by_builtin_and_secondary_trusted(
> >>>>>  * Allocate a struct key_restriction for the "builtin and secondary trust"
> >>>>>  * keyring. Only for use in system_trusted_keyring_init().
> >>>>>  */
> >>>>> -static __init struct key_restriction *get_builtin_and_secondary_restriction(void)
> >>>>> +static __init struct key_restriction *get_secondary_restriction(void)
> >>>>> {
> >>>>>        struct key_restriction *restriction;
> >>>>> 
> >>>>> @@ -117,7 +117,7 @@ static __init int system_trusted_keyring_init(void)
> >>>>>                               KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH |
> >>>>>                               KEY_USR_WRITE),
> >>>>>                              KEY_ALLOC_NOT_IN_QUOTA,
> >>>>> -                             get_builtin_and_secondary_restriction(),
> >>>>> +                             get_secondary_restriction(),
> >>>>>                              NULL);
> >>>>>        if (IS_ERR(secondary_trusted_keys))
> >>>>>                panic("Can't allocate secondary trusted keyring\n");
> >>>> 
> >>>> This is wrong order.
> >>>> 
> >>>> You should first do the changes that make the old name
> >>>> obsolete and only after that have a patch that does the
> >>>> rename. Unfortunately, this patch cannot possibly acked
> >>>> with the current order.
> >>> 
> >>> I can change the order, but I'm confused how this would work for a git bisect. 
> >>> If the rename happens afterwards, now two patches will always need to be 
> >>> reverted instead of the possibility of one.  Is this your expectation?
> > 
> > If the keyring name change is independent of any other changes, as
> > Jarkko suggested, nothing would break.
> > 
> >> I'd drop this patch altogether. Old name is a bit ugly but does it matter
> >> all that much?
> > 
> > The name "get_builtin_and_secondary_restriction" implies trust based on
> > keys in the ".builtin_trusted_keys" and ".secondary_trusted_keys"
> > keyrings.  This patch set is extending that to include keys on the new
> > ".machine" keyring, by linking it to the secondary keyring.  Is leaving
> > the name unchanged really an option?
> > 
> >> 
> >> You already 16 patches without this.
> > 
> > Agreed, it's a lot.  In the past, I've asked Eric to see if some of
> > them could be squashed.
> 
> The series grew based on requests added in each round.  How about
> I drop IMA support from the next round?  This would eliminate nine patches
> from the series (5, 6, 7, 9-14), leaving six patches to introduce and enable 
> the new machine keyring (3, 4, 8, 15-17).  The first two patches could 
> be taken today.  The only reason the first two are included is to get this series 
> through the kernel test robot.
> 
> This would allow the machine keyring to be used for module signing.  Afterwards 
> I could introduce the CA restriction behind another Kconfig in a different series to 
> add back IMA support. Let me know if this would be a better approach.

Once you allow ALL the MOK keys to be loaded onto the .machine keyring,
limiting which keys should be loaded will change the existing expected
behavior.  So you indeed would need to define a new config option.

Your patch set links the ".machine" keyring to the
".secondary_trusted_keys" kerying. Based on
IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY config being
enabled, determines whether IMA trusts the secondary keyring.
Jarkko Sakkinen Feb. 20, 2022, 11:23 p.m. UTC | #8
On Tue, Nov 23, 2021 at 11:41:07PM -0500, Eric Snowberg wrote:
> Back in 2013 Linus requested a feature to allow end-users to have the 
> ability "to add their own keys and sign modules they trust". This was
> his *second* order outlined here [1]. There have been many attempts 
> over the years to solve this problem, all have been rejected.  Many 
> of the failed attempts loaded all preboot firmware keys into the kernel,
> including the Secure Boot keys. Many distributions carry one of these 
> rejected attempts [2], [3], [4]. This series tries to solve this problem 
> with a solution that takes into account all the problems brought up in 
> the previous attempts.
> 
> On UEFI based systems, this series introduces a new Linux kernel keyring 
> containing the Machine Owner Keys (MOK) called machine. It also defines
> a new MOK variable in shim. This variable allows the end-user to decide 
> if they want to load MOK keys into the machine keyring. Mimi has suggested 
> that only CA keys contained within the MOK be loaded into the machine 
> keyring. All other certs will load into the platform keyring instead.
> 
> By default, nothing changes; MOK keys are not loaded into the machine
> keyring.  They are only loaded after the end-user makes the decision 
> themselves.  The end-user would set this through mokutil using a new 
> --trust-mok option [5]. This would work similar to how the kernel uses 
> MOK variables to enable/disable signature validation as well as use/ignore 
> the db. Any kernel operation that uses either the builtin or secondary 
> trusted keys as a trust source shall also reference the new machine 
> keyring as a trust source.
> 
> Secure Boot keys will never be loaded into the machine keyring.  They
> will always be loaded into the platform keyring.  If an end-user wanted 
> to load one, they would need to enroll it into the MOK.
> 
> Steps required by the end user:
> 
> Sign kernel module with user created key:
> $ /usr/src/kernels/$(uname -r)/scripts/sign-file sha512 \
>    machine_signing_key.priv machine_signing_key.x509 my_module.ko
> 
> Import the key into the MOK
> $ mokutil --import machine_signing_key.x509
> 
> Setup the kernel to load MOK keys into the .machine keyring
> $ mokutil --trust-mok
> 
> Then reboot, the MokManager will load and ask if you want to trust the
> MOK key and enroll the MOK into the MOKList.  Afterwards the signed kernel
> module will load.
> 
> I have included  a link to the mokutil [5] changes I have made to support 
> this new functionality.  The shim changes have now been accepted
> upstream [6].
> 
> Upstream shim is located here [7], the build instructions are here [8].
> TLDR:
> 
> $ git clone --recurse-submodules https://github.com/rhboot/shim
> $ cd shim
> $ make
> 
> After building shim, move shimx64.efi and mmx64.efi to the vendor or 
> distribution specific directory on your EFI System Partition (assuming
> you are building on x86). The instructions above are the minimal
> steps needed to build shim to test this feature. It is assumed
> Secure Boot shall not be enabled for this testing. To do testing
> with Secure Boot enabled, all steps in the build instructions [8]
> must be followed.
> 
> Instructions for building mokutil (including the new changes):
> 
> $ git clone -b mokvars-v3 https://github.com/esnowberg/mokutil.git
> $ cd mokutil/
> $ ./autogen.sh
> $ make
> 
> [1] https://marc.info/?l=linux-kernel&m=136185386310140&w=2
> [2] https://lore.kernel.org/lkml/1479737095.2487.34.camel@linux.vnet.ibm.com/
> [3] https://lore.kernel.org/lkml/1556221605.24945.3.camel@HansenPartnership.com/
> [4] https://lore.kernel.org/linux-integrity/1e41f22b1f11784f1e943f32bf62034d4e054cdb.camel@HansenPartnership.com/
> [5] https://github.com/esnowberg/mokutil/tree/mokvars-v3
> [6] https://github.com/rhboot/shim/commit/4e513405b4f1641710115780d19dcec130c5208f
> [7] https://github.com/rhboot/shim
> [8] https://github.com/rhboot/shim/blob/main/BUILDING
> 
> 
> Eric Snowberg (17):
>   KEYS: Create static version of public_key_verify_signature
>   integrity: Fix warning about missing prototypes
>   integrity: Introduce a Linux keyring called machine
>   integrity: Do not allow machine keyring updates following init
>   X.509: Parse Basic Constraints for CA
>   KEYS: CA link restriction
>   integrity: restrict INTEGRITY_KEYRING_MACHINE to restrict_link_by_ca
>   integrity: add new keyring handler for mok keys
>   KEYS: Rename get_builtin_and_secondary_restriction
>   KEYS: add a reference to machine keyring
>   KEYS: Introduce link restriction for machine keys
>   KEYS: integrity: change link restriction to trust the machine keyring
>   integrity: store reference to machine keyring
>   KEYS: link machine trusted keys to secondary_trusted_keys
>   efi/mokvar: move up init order
>   integrity: Trust MOK keys if MokListTrustedRT found
>   integrity: Only use machine keyring when uefi_check_trust_mok_keys is
>     true
> 
>  certs/system_keyring.c                        | 48 +++++++++++-
>  crypto/asymmetric_keys/restrict.c             | 43 +++++++++++
>  crypto/asymmetric_keys/x509_cert_parser.c     |  9 +++
>  drivers/firmware/efi/mokvar-table.c           |  2 +-
>  include/crypto/public_key.h                   | 25 ++++++
>  include/keys/system_keyring.h                 | 14 ++++
>  security/integrity/Kconfig                    | 12 +++
>  security/integrity/Makefile                   |  1 +
>  security/integrity/digsig.c                   | 23 +++++-
>  security/integrity/integrity.h                | 17 +++-
>  .../platform_certs/keyring_handler.c          | 18 ++++-
>  .../platform_certs/keyring_handler.h          |  5 ++
>  security/integrity/platform_certs/load_uefi.c |  4 +-
>  .../platform_certs/machine_keyring.c          | 77 +++++++++++++++++++
>  14 files changed, 287 insertions(+), 11 deletions(-)
>  create mode 100644 security/integrity/platform_certs/machine_keyring.c
> 
> 
> base-commit: 136057256686de39cc3a07c2e39ef6bc43003ff6
> -- 
> 2.18.4
> 

When I try to apply this:

$ b4  am 20211124044124.998170-8-eric.snowberg@oracle.com
Looking up https://lore.kernel.org/r/20211124044124.998170-8-eric.snowberg%40oracle.com
Analyzing 40 messages in the thread
Checking attestation on all messages, may take a moment...
# ...
$ git am -3 v8_20211123_eric_snowberg_enroll_kernel_keys_thru_mok.mbx
Applying: KEYS: Create static version of public_key_verify_signature
Applying: integrity: Fix warning about missing prototypes
Applying: integrity: Introduce a Linux keyring called machine
Applying: integrity: Do not allow machine keyring updates following init
Applying: X.509: Parse Basic Constraints for CA
Applying: KEYS: CA link restriction
error: sha1 information is lacking or useless (include/crypto/public_key.h).
error: could not build fake ancestor
Patch failed at 0006 KEYS: CA link restriction
hint: Use 'git am --show-current-patch=diff' to see the failed patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".

BR, Jarkko