* Re: [PATCH 4/4] module, KEYS: Make use of platform keyring for signature verification
From: Mimi Zohar @ 2022-02-16 11:58 UTC (permalink / raw)
To: Michal Suchánek
Cc: Catalin Marinas, Will Deacon, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Philipp Rudo, Baoquan He, Alexander Egorenkov, AKASHI Takahiro,
James Morse, Dave Young, Kairui Song, Martin Schwidefsky,
linux-arm-kernel, linux-kernel, linux-s390, linux-modules,
keyrings, linux-security-module, stable, Eric Snowberg
In-Reply-To: <20220216105645.GS3113@kunlun.suse.cz>
On Wed, 2022-02-16 at 11:56 +0100, Michal Suchánek wrote:
> On Tue, Feb 15, 2022 at 05:12:32PM -0500, Mimi Zohar wrote:
> > On Tue, 2022-02-15 at 21:47 +0100, Michal Suchánek wrote:
> > > Hello,
> > >
> > > On Tue, Feb 15, 2022 at 03:08:18PM -0500, Mimi Zohar wrote:
> > > > [Cc'ing Eric Snowberg]
> > > >
> > > > Hi Michal,
> > > >
> > > > On Tue, 2022-02-15 at 20:39 +0100, Michal Suchanek wrote:
> > > > > Commit 278311e417be ("kexec, KEYS: Make use of platform keyring for signature verify")
> > > > > adds support for use of platform keyring in kexec verification but
> > > > > support for modules is missing.
> > > > >
> > > > > Add support for verification of modules with keys from platform keyring
> > > > > as well.
> > > >
> > > > Permission for loading the pre-OS keys onto the "platform" keyring and
> > > > using them is limited to verifying the kexec kernel image, nothing
> > > > else.
> > >
> > > Why is the platform keyring limited to kexec, and nothing else?
> > >
> > > It should either be used for everything or for nothing. You have the
> > > option to compile it in and then it should be used, and the option to
> > > not compile it in and then it cannot be used.
> > >
> > > There are two basic use cases:
> > >
> > > (1) there is a vendor key which is very hard to use so you sign
> > > something small and simple like shim with the vendor key, and sign your
> > > kernel and modules with your own key that's typically enrolled with shim
> > > MOK, and built into the kernel.
> > >
> > > (2) you import your key into the firmware, and possibly disable the
> > > vendor key. You can load the kernel directly without shim, and then your
> > > signing key is typically in the platform keyring and built into the
> > > kernel.
> > >
> > > In neither case do I see any reason to use some keyrings for kexec and
> > > other keyrings for modules.
> >
> > When building your own kernel there isn't a problem. Additional keys
> > may be built into the kernel image, which are loaded onto the
> > ".builtin_trusted_keys" keyring, and may be stored in MOK. Normally
> > different keys are used for signing the kernel image and kernel
>
> That's actually not normal.
>
> > modules. Kernel modules can be signed by the build time ephemeral
> > kernel module signing key, which is built into the kernel and
> > automatically loaded onto the ".builtin_trusted_keys" keyring.
>
> Right, there is this advice to use ephemeral key to sign modules.
>
> I don't think that's a sound advice in general. It covers only the
> special case when you build the kernel once, only rebuild the whole
> kernel and never just one module, don't use any 3rd party module, don't
> bother signing firmware (I am not sure that is supported right now but
> if you are into integrity and stuff you can see that it makes sense to
> sign it, too).
>
> And you need to manage the key you use for the kernel signing, anyway.
> Sure, you could use the same ephemeral key as for the modules, enroll
> it, and shred it but then it is NOT a key different from the one you use
> for modules.
>
> Or you could maintain a long-lived key for the kernel, but if you do I
> do NOT see any reason to not use it also for modules, in-tree and
> out-of-tree.
If signing ALL kernel modules, in-tree and out-of-tree, with the same
key as the kernel image, is your real intention, then by all means
write a complete patch description with the motivation for why kernel
module signatures need to be verified against this one pre-OS key
stored only in the platform keyring. Such a major change like this
shouldn't be buried here.
Otherwise, I suggest looking at Eric Snowberg's "Enroll kernel keys
thru MOK patch set" patch set [1], as previously mentioned, which is
queued to be upstreamed by Jarkko. It loads MOK keys onto the
'.machine' keyring, which is linked to the '.secondary_trusted_keys"
keyring. A subsequent patch set will enable IMA support.
[1]
https://lore.kernel.org/lkml/20220126025834.255493-1-eric.snowberg@oracle.com/
--
thanks,
Mimi
^ permalink raw reply
* Re: [PATCH 4/4] module, KEYS: Make use of platform keyring for signature verification
From: Michal Suchánek @ 2022-02-16 11:04 UTC (permalink / raw)
To: Mimi Zohar
Cc: Catalin Marinas, Will Deacon, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Philipp Rudo, Baoquan He, Alexander Egorenkov, AKASHI Takahiro,
James Morse, Dave Young, Kairui Song, Martin Schwidefsky,
linux-arm-kernel, linux-kernel, linux-s390, linux-modules,
keyrings, linux-security-module, stable, Eric Snowberg
In-Reply-To: <20220216105645.GS3113@kunlun.suse.cz>
On Wed, Feb 16, 2022 at 11:56:45AM +0100, Michal Suchánek wrote:
> On Tue, Feb 15, 2022 at 05:12:32PM -0500, Mimi Zohar wrote:
> > On Tue, 2022-02-15 at 21:47 +0100, Michal Suchánek wrote:
> > > Hello,
> > >
> > > On Tue, Feb 15, 2022 at 03:08:18PM -0500, Mimi Zohar wrote:
> > > > [Cc'ing Eric Snowberg]
> > > >
> > > > Hi Michal,
> > > >
> > > > On Tue, 2022-02-15 at 20:39 +0100, Michal Suchanek wrote:
> > > > > Commit 278311e417be ("kexec, KEYS: Make use of platform keyring for signature verify")
> > > > > adds support for use of platform keyring in kexec verification but
> > > > > support for modules is missing.
> > > > >
> > > > > Add support for verification of modules with keys from platform keyring
> > > > > as well.
> > > >
> > > > Permission for loading the pre-OS keys onto the "platform" keyring and
> > > > using them is limited to verifying the kexec kernel image, nothing
> > > > else.
> > >
> > > Why is the platform keyring limited to kexec, and nothing else?
> > >
> > > It should either be used for everything or for nothing. You have the
> > > option to compile it in and then it should be used, and the option to
> > > not compile it in and then it cannot be used.
> > >
> > > There are two basic use cases:
> > >
> > > (1) there is a vendor key which is very hard to use so you sign
> > > something small and simple like shim with the vendor key, and sign your
> > > kernel and modules with your own key that's typically enrolled with shim
> > > MOK, and built into the kernel.
> > >
> > > (2) you import your key into the firmware, and possibly disable the
> > > vendor key. You can load the kernel directly without shim, and then your
> > > signing key is typically in the platform keyring and built into the
> > > kernel.
> > >
> > > In neither case do I see any reason to use some keyrings for kexec and
> > > other keyrings for modules.
> >
> > When building your own kernel there isn't a problem. Additional keys
> > may be built into the kernel image, which are loaded onto the
> > ".builtin_trusted_keys" keyring, and may be stored in MOK. Normally
> > different keys are used for signing the kernel image and kernel
>
> That's actually not normal.
>
> > modules. Kernel modules can be signed by the build time ephemeral
> > kernel module signing key, which is built into the kernel and
> > automatically loaded onto the ".builtin_trusted_keys" keyring.
>
> Right, there is this advice to use ephemeral key to sign modules.
>
> I don't think that's a sound advice in general. It covers only the
> special case when you build the kernel once, only rebuild the whole
> kernel and never just one module, don't use any 3rd party module, don't
> bother signing firmware (I am not sure that is supported right now but
> if you are into integrity and stuff you can see that it makes sense to
> sign it, too).
And don't forget signing ramdisk which you typically don't build only
once at kernel build time.
>
> And you need to manage the key you use for the kernel signing, anyway.
> Sure, you could use the same ephemeral key as for the modules, enroll
> it, and shred it but then it is NOT a key different from the one you use
> for modules.
>
> Or you could maintain a long-lived key for the kernel, but if you do I
> do NOT see any reason to not use it also for modules, in-tree and
> out-of-tree.
>
> > Similarly distros build the kernel module signing key into the kernel,
> > which is built into the kernel and loaded onto the
> > ".builtin_trusted_keys" keyring. By loading the pre-OS keys onto the
> > ".platform" keyring, kexec may verify the distro or other signed
> > kernel images.
>
> Which are signed by the same key as the modules so there is no reason to
> load the platform key at all. I don't think loading shim with kexec is
> supported.
>
> Thanks
>
> Michal
^ permalink raw reply
* Re: [PATCH 4/4] module, KEYS: Make use of platform keyring for signature verification
From: Michal Suchánek @ 2022-02-16 10:56 UTC (permalink / raw)
To: Mimi Zohar
Cc: Catalin Marinas, Will Deacon, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Philipp Rudo, Baoquan He, Alexander Egorenkov, AKASHI Takahiro,
James Morse, Dave Young, Kairui Song, Martin Schwidefsky,
linux-arm-kernel, linux-kernel, linux-s390, linux-modules,
keyrings, linux-security-module, stable, Eric Snowberg
In-Reply-To: <c3f6f6c8a9db34cc1cdc1000f9272c2b36445e15.camel@linux.ibm.com>
On Tue, Feb 15, 2022 at 05:12:32PM -0500, Mimi Zohar wrote:
> On Tue, 2022-02-15 at 21:47 +0100, Michal Suchánek wrote:
> > Hello,
> >
> > On Tue, Feb 15, 2022 at 03:08:18PM -0500, Mimi Zohar wrote:
> > > [Cc'ing Eric Snowberg]
> > >
> > > Hi Michal,
> > >
> > > On Tue, 2022-02-15 at 20:39 +0100, Michal Suchanek wrote:
> > > > Commit 278311e417be ("kexec, KEYS: Make use of platform keyring for signature verify")
> > > > adds support for use of platform keyring in kexec verification but
> > > > support for modules is missing.
> > > >
> > > > Add support for verification of modules with keys from platform keyring
> > > > as well.
> > >
> > > Permission for loading the pre-OS keys onto the "platform" keyring and
> > > using them is limited to verifying the kexec kernel image, nothing
> > > else.
> >
> > Why is the platform keyring limited to kexec, and nothing else?
> >
> > It should either be used for everything or for nothing. You have the
> > option to compile it in and then it should be used, and the option to
> > not compile it in and then it cannot be used.
> >
> > There are two basic use cases:
> >
> > (1) there is a vendor key which is very hard to use so you sign
> > something small and simple like shim with the vendor key, and sign your
> > kernel and modules with your own key that's typically enrolled with shim
> > MOK, and built into the kernel.
> >
> > (2) you import your key into the firmware, and possibly disable the
> > vendor key. You can load the kernel directly without shim, and then your
> > signing key is typically in the platform keyring and built into the
> > kernel.
> >
> > In neither case do I see any reason to use some keyrings for kexec and
> > other keyrings for modules.
>
> When building your own kernel there isn't a problem. Additional keys
> may be built into the kernel image, which are loaded onto the
> ".builtin_trusted_keys" keyring, and may be stored in MOK. Normally
> different keys are used for signing the kernel image and kernel
That's actually not normal.
> modules. Kernel modules can be signed by the build time ephemeral
> kernel module signing key, which is built into the kernel and
> automatically loaded onto the ".builtin_trusted_keys" keyring.
Right, there is this advice to use ephemeral key to sign modules.
I don't think that's a sound advice in general. It covers only the
special case when you build the kernel once, only rebuild the whole
kernel and never just one module, don't use any 3rd party module, don't
bother signing firmware (I am not sure that is supported right now but
if you are into integrity and stuff you can see that it makes sense to
sign it, too).
And you need to manage the key you use for the kernel signing, anyway.
Sure, you could use the same ephemeral key as for the modules, enroll
it, and shred it but then it is NOT a key different from the one you use
for modules.
Or you could maintain a long-lived key for the kernel, but if you do I
do NOT see any reason to not use it also for modules, in-tree and
out-of-tree.
> Similarly distros build the kernel module signing key into the kernel,
> which is built into the kernel and loaded onto the
> ".builtin_trusted_keys" keyring. By loading the pre-OS keys onto the
> ".platform" keyring, kexec may verify the distro or other signed
> kernel images.
Which are signed by the same key as the modules so there is no reason to
load the platform key at all. I don't think loading shim with kexec is
supported.
Thanks
Michal
^ permalink raw reply
* Re: [PATCH 4/4] module, KEYS: Make use of platform keyring for signature verification
From: Mimi Zohar @ 2022-02-15 22:12 UTC (permalink / raw)
To: Michal Suchánek
Cc: Catalin Marinas, Will Deacon, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Philipp Rudo, Baoquan He, Alexander Egorenkov, AKASHI Takahiro,
James Morse, Dave Young, Kairui Song, Martin Schwidefsky,
linux-arm-kernel, linux-kernel, linux-s390, linux-modules,
keyrings, linux-security-module, stable, Eric Snowberg
In-Reply-To: <20220215204730.GQ3113@kunlun.suse.cz>
On Tue, 2022-02-15 at 21:47 +0100, Michal Suchánek wrote:
> Hello,
>
> On Tue, Feb 15, 2022 at 03:08:18PM -0500, Mimi Zohar wrote:
> > [Cc'ing Eric Snowberg]
> >
> > Hi Michal,
> >
> > On Tue, 2022-02-15 at 20:39 +0100, Michal Suchanek wrote:
> > > Commit 278311e417be ("kexec, KEYS: Make use of platform keyring for signature verify")
> > > adds support for use of platform keyring in kexec verification but
> > > support for modules is missing.
> > >
> > > Add support for verification of modules with keys from platform keyring
> > > as well.
> >
> > Permission for loading the pre-OS keys onto the "platform" keyring and
> > using them is limited to verifying the kexec kernel image, nothing
> > else.
>
> Why is the platform keyring limited to kexec, and nothing else?
>
> It should either be used for everything or for nothing. You have the
> option to compile it in and then it should be used, and the option to
> not compile it in and then it cannot be used.
>
> There are two basic use cases:
>
> (1) there is a vendor key which is very hard to use so you sign
> something small and simple like shim with the vendor key, and sign your
> kernel and modules with your own key that's typically enrolled with shim
> MOK, and built into the kernel.
>
> (2) you import your key into the firmware, and possibly disable the
> vendor key. You can load the kernel directly without shim, and then your
> signing key is typically in the platform keyring and built into the
> kernel.
>
> In neither case do I see any reason to use some keyrings for kexec and
> other keyrings for modules.
When building your own kernel there isn't a problem. Additional keys
may be built into the kernel image, which are loaded onto the
".builtin_trusted_keys" keyring, and may be stored in MOK. Normally
different keys are used for signing the kernel image and kernel
modules. Kernel modules can be signed by the build time ephemeral
kernel module signing key, which is built into the kernel and
automatically loaded onto the ".builtin_trusted_keys" keyring.
Similarly distros build the kernel module signing key into the kernel,
which is built into the kernel and loaded onto the
".builtin_trusted_keys" keyring. By loading the pre-OS keys onto the
".platform" keyring, kexec may verify the distro or other signed
kernel images.
--
thanks,
Mimi
^ permalink raw reply
* Re: [PATCH 4/4] module, KEYS: Make use of platform keyring for signature verification
From: Michal Suchánek @ 2022-02-15 20:47 UTC (permalink / raw)
To: Mimi Zohar
Cc: Catalin Marinas, Will Deacon, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Philipp Rudo, Baoquan He, Alexander Egorenkov, AKASHI Takahiro,
James Morse, Dave Young, Kairui Song, Martin Schwidefsky,
linux-arm-kernel, linux-kernel, linux-s390, linux-modules,
keyrings, linux-security-module, stable, Eric Snowberg
In-Reply-To: <3e39412657a4b0839bcf38544d591959e89877b8.camel@linux.ibm.com>
Hello,
On Tue, Feb 15, 2022 at 03:08:18PM -0500, Mimi Zohar wrote:
> [Cc'ing Eric Snowberg]
>
> Hi Michal,
>
> On Tue, 2022-02-15 at 20:39 +0100, Michal Suchanek wrote:
> > Commit 278311e417be ("kexec, KEYS: Make use of platform keyring for signature verify")
> > adds support for use of platform keyring in kexec verification but
> > support for modules is missing.
> >
> > Add support for verification of modules with keys from platform keyring
> > as well.
>
> Permission for loading the pre-OS keys onto the "platform" keyring and
> using them is limited to verifying the kexec kernel image, nothing
> else.
Why is the platform keyring limited to kexec, and nothing else?
It should either be used for everything or for nothing. You have the
option to compile it in and then it should be used, and the option to
not compile it in and then it cannot be used.
There are two basic use cases:
(1) there is a vendor key which is very hard to use so you sign
something small and simple like shim with the vendor key, and sign your
kernel and modules with your own key that's typically enrolled with shim
MOK, and built into the kernel.
(2) you import your key into the firmware, and possibly disable the
vendor key. You can load the kernel directly without shim, and then your
signing key is typically in the platform keyring and built into the
kernel.
In neither case do I see any reason to use some keyrings for kexec and
other keyrings for modules.
Thanks
Michal
^ permalink raw reply
* Re: [PATCH 4/4] module, KEYS: Make use of platform keyring for signature verification
From: Mimi Zohar @ 2022-02-15 20:08 UTC (permalink / raw)
To: Michal Suchanek
Cc: Catalin Marinas, Will Deacon, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Philipp Rudo, Baoquan He, Alexander Egorenkov, AKASHI Takahiro,
James Morse, Dave Young, Kairui Song, Martin Schwidefsky,
linux-arm-kernel, linux-kernel, linux-s390, linux-modules,
keyrings, linux-security-module, stable, Eric Snowberg
In-Reply-To: <840433bc93a58d6dfc4d96c34c0c3b158a0e669d.1644953683.git.msuchanek@suse.de>
[Cc'ing Eric Snowberg]
Hi Michal,
On Tue, 2022-02-15 at 20:39 +0100, Michal Suchanek wrote:
> Commit 278311e417be ("kexec, KEYS: Make use of platform keyring for signature verify")
> adds support for use of platform keyring in kexec verification but
> support for modules is missing.
>
> Add support for verification of modules with keys from platform keyring
> as well.
Permission for loading the pre-OS keys onto the "platform" keyring and
using them is limited to verifying the kexec kernel image, nothing
else.
FYI, Eric Snowberg's initial patch set titled "[PATCH v10 0/8] Enroll
kernel keys thru MOK" is queued in Jarkko's git repo to be usptreamed.
A subsequent patch set is expected.
--
thanks,
Mimi
[1] Message-Id: <20211124044124.998170-11-eric.snowberg@oracle.com>
^ permalink raw reply
* Re: [PATCH net v3 0/2] security: fixups for the security hooks in sctp
From: Paul Moore @ 2022-02-15 20:08 UTC (permalink / raw)
To: Ondrej Mosnacek
Cc: netdev, davem, kuba, selinux, Xin Long, Richard Haines,
Vlad Yasevich, Neil Horman, Marcelo Ricardo Leitner, linux-sctp,
linux-security-module, linux-kernel
In-Reply-To: <20220212175922.665442-1-omosnace@redhat.com>
On Sat, Feb 12, 2022 at 12:59 PM Ondrej Mosnacek <omosnace@redhat.com> wrote:
>
> This is a third round of patches to fix the SCTP-SELinux interaction
> w.r.t. client-side peeloff. The patches are a modified version of Xin
> Long's patches posted previously, of which only a part was merged (the
> rest was merged for a while, but was later reverted):
> https://lore.kernel.org/selinux/cover.1635854268.git.lucien.xin@gmail.com/T/
>
> In gist, these patches replace the call to
> security_inet_conn_established() in SCTP with a new hook
> security_sctp_assoc_established() and implement the new hook in SELinux
> so that the client-side association labels are set correctly (which
> matters in case the association eventually gets peeled off into a
> separate socket).
>
> Note that other LSMs than SELinux don't implement the SCTP hooks nor
> inet_conn_established, so they shouldn't be affected by any of these
> changes.
>
> These patches were tested by selinux-testsuite [1] with an additional
> patch [2] and by lksctp-tools func_tests [3].
>
> Changes since v2:
> - patches 1 and 2 dropped as they are already in mainline (not reverted)
> - in patch 3, the return value of security_sctp_assoc_established() is
> changed to int, the call is moved earlier in the function, and if the
> hook returns an error value, the packet will now be discarded,
> aborting the association
> - patch 4 has been changed a lot - please see the patch description for
> details on how the hook is now implemented and why
>
> [1] https://github.com/SELinuxProject/selinux-testsuite/
> [2] https://patchwork.kernel.org/project/selinux/patch/20211021144543.740762-1-omosnace@redhat.com/
> [3] https://github.com/sctp/lksctp-tools/tree/master/src/func_tests
>
> Ondrej Mosnacek (2):
> security: add sctp_assoc_established hook
> security: implement sctp_assoc_established hook in selinux
>
> Documentation/security/SCTP.rst | 22 ++++----
> include/linux/lsm_hook_defs.h | 2 +
> include/linux/lsm_hooks.h | 5 ++
> include/linux/security.h | 8 +++
> net/sctp/sm_statefuns.c | 8 +--
> security/security.c | 7 +++
> security/selinux/hooks.c | 90 ++++++++++++++++++++++++---------
> 7 files changed, 103 insertions(+), 39 deletions(-)
This patchset has been merged into selinux/next, thanks everyone!
--
paul-moore.com
^ permalink raw reply
* Re: [PATCH net v3 2/2] security: implement sctp_assoc_established hook in selinux
From: Paul Moore @ 2022-02-15 20:02 UTC (permalink / raw)
To: Xin Long
Cc: Marcelo Ricardo Leitner, Jakub Kicinski, Ondrej Mosnacek, netdev,
David Miller, SElinux list, Richard Haines, Vlad Yasevich,
Neil Horman, open list:SCTP PROTOCOL, LSM List, LKML,
Prashanth Prahlad
In-Reply-To: <CADvbK_e+TUuWhBQz1NPPS2aE59tzPKXPfUogrZ526hvm6OvY9Q@mail.gmail.com>
On Mon, Feb 14, 2022 at 11:13 PM Xin Long <lucien.xin@gmail.com> wrote:
> Looks okay to me.
>
> The difference from the old one is that: with
> selinux_sctp_process_new_assoc() called in
> selinux_sctp_assoc_established(), the client sksec->peer_sid is using
> the first asoc's peer_secid, instead of the latest asoc's peer_secid.
> And not sure if it will cause any problems when doing the extra check
> sksec->peer_sid != asoc->peer_secid for the latest asoc and *returns
> err*. But I don't know about selinux, I guess there must be a reason
> from selinux side.
Generally speaking we don't want to change any SELinux socket labels
once it has been created. While the peer_sid is a bit different,
changing it after userspace has access to the socket could be
problematic. In the case where the peer_sid differs between the two
we have a permission check which allows policy to control this
behavior which seems like the best option at this point.
> I will ACK on patch 0/2.
Thanks, I'm going to go ahead and merge these two patches into
selinux/next right now.
--
paul-moore.com
^ permalink raw reply
* [PATCH 4/4] module, KEYS: Make use of platform keyring for signature verification
From: Michal Suchanek @ 2022-02-15 19:39 UTC (permalink / raw)
Cc: Michal Suchanek, Catalin Marinas, Will Deacon, Heiko Carstens,
Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
Sven Schnelle, Philipp Rudo, Baoquan He, Alexander Egorenkov,
AKASHI Takahiro, James Morse, Dave Young, Mimi Zohar, Kairui Song,
Martin Schwidefsky, linux-arm-kernel, linux-kernel, linux-s390,
linux-modules, keyrings, linux-security-module, stable
In-Reply-To: <cover.1644953683.git.msuchanek@suse.de>
Commit 278311e417be ("kexec, KEYS: Make use of platform keyring for signature verify")
adds support for use of platform keyring in kexec verification but
support for modules is missing.
Add support for verification of modules with keys from platform keyring
as well.
Fixes: 219a3e8676f3 ("integrity, KEYS: add a reference to platform keyring")
Cc: linux-modules@vger.kernel.org
Cc: keyrings@vger.kernel.org
Cc: linux-security-module@vger.kernel.org
Cc: stable@kernel.org
Signed-off-by: Michal Suchanek <msuchanek@suse.de>
---
kernel/module_signing.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/kernel/module_signing.c b/kernel/module_signing.c
index 8723ae70ea1f..5e1624294874 100644
--- a/kernel/module_signing.c
+++ b/kernel/module_signing.c
@@ -38,8 +38,14 @@ int mod_verify_sig(const void *mod, struct load_info *info)
modlen -= sig_len + sizeof(ms);
info->len = modlen;
- return verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len,
- VERIFY_USE_SECONDARY_KEYRING,
- VERIFYING_MODULE_SIGNATURE,
- NULL, NULL);
+ ret = verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len,
+ VERIFY_USE_SECONDARY_KEYRING,
+ VERIFYING_MODULE_SIGNATURE,
+ NULL, NULL);
+ if (ret == -ENOKEY && IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING))
+ ret = verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len,
+ VERIFY_USE_PLATFORM_KEYRING,
+ VERIFYING_MODULE_SIGNATURE,
+ NULL, NULL);
+ return ret;
}
--
2.31.1
^ permalink raw reply related
* [PATCH 3/4] kexec, KEYS, s390: Make use of built-in and secondary keyring for signature verification
From: Michal Suchanek @ 2022-02-15 19:39 UTC (permalink / raw)
Cc: Michal Suchanek, Catalin Marinas, Will Deacon, Heiko Carstens,
Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
Sven Schnelle, Philipp Rudo, Baoquan He, Alexander Egorenkov,
AKASHI Takahiro, James Morse, Dave Young, Mimi Zohar, Kairui Song,
Martin Schwidefsky, linux-arm-kernel, linux-kernel, linux-s390,
Philipp Rudo, kexec, keyrings, linux-security-module, stable
In-Reply-To: <cover.1644953683.git.msuchanek@suse.de>
commit e23a8020ce4e ("s390/kexec_file: Signature verification prototype")
adds support for KEXEC_SIG verification with keys from platform keyring
but the built-in keys and secondary keyring are not used.
Add support for the built-in keys and secondary keyring as x86 does.
Fixes: e23a8020ce4e ("s390/kexec_file: Signature verification prototype")
Cc: Philipp Rudo <prudo@linux.ibm.com>
Cc: kexec@lists.infradead.org
Cc: keyrings@vger.kernel.org
Cc: linux-security-module@vger.kernel.org
Cc: stable@kernel.org
Signed-off-by: Michal Suchanek <msuchanek@suse.de>
---
arch/s390/kernel/machine_kexec_file.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/arch/s390/kernel/machine_kexec_file.c b/arch/s390/kernel/machine_kexec_file.c
index 8f43575a4dd3..fc6d5f58debe 100644
--- a/arch/s390/kernel/machine_kexec_file.c
+++ b/arch/s390/kernel/machine_kexec_file.c
@@ -31,6 +31,7 @@ int s390_verify_sig(const char *kernel, unsigned long kernel_len)
const unsigned long marker_len = sizeof(MODULE_SIG_STRING) - 1;
struct module_signature *ms;
unsigned long sig_len;
+ int ret;
/* Skip signature verification when not secure IPLed. */
if (!ipl_secure_flag)
@@ -65,11 +66,18 @@ int s390_verify_sig(const char *kernel, unsigned long kernel_len)
return -EBADMSG;
}
- return verify_pkcs7_signature(kernel, kernel_len,
- kernel + kernel_len, sig_len,
- VERIFY_USE_PLATFORM_KEYRING,
- VERIFYING_MODULE_SIGNATURE,
- NULL, NULL);
+ ret = verify_pkcs7_signature(kernel, kernel_len,
+ kernel + kernel_len, sig_len,
+ VERIFY_USE_SECONDARY_KEYRING,
+ VERIFYING_MODULE_SIGNATURE,
+ NULL, NULL);
+ if (ret == -ENOKEY && IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING))
+ ret = verify_pkcs7_signature(kernel, kernel_len,
+ kernel + kernel_len, sig_len,
+ VERIFY_USE_PLATFORM_KEYRING,
+ VERIFYING_MODULE_SIGNATURE,
+ NULL, NULL);
+ return ret;
}
#endif /* CONFIG_KEXEC_SIG */
--
2.31.1
^ permalink raw reply related
* [PATCH 2/4] kexec, KEYS, arm64: Make use of platform keyring for signature verification
From: Michal Suchanek @ 2022-02-15 19:39 UTC (permalink / raw)
Cc: Michal Suchanek, Catalin Marinas, Will Deacon, Heiko Carstens,
Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
Sven Schnelle, Philipp Rudo, Baoquan He, Alexander Egorenkov,
AKASHI Takahiro, James Morse, Dave Young, Mimi Zohar, Kairui Song,
Martin Schwidefsky, linux-arm-kernel, linux-kernel, linux-s390,
kexec, keyrings, linux-security-module, stable
In-Reply-To: <cover.1644953683.git.msuchanek@suse.de>
commit 278311e417be ("kexec, KEYS: Make use of platform keyring for signature verify")
adds platform keyring support on x86 kexec but not arm64.
Add platform keyring support on arm64 as well.
Fixes: 278311e417be ("kexec, KEYS: Make use of platform keyring for signature verify")
Cc: kexec@lists.infradead.org
Cc: keyrings@vger.kernel.org
Cc: linux-security-module@vger.kernel.org
Cc: stable@kernel.org
Signed-off-by: Michal Suchanek <msuchanek@suse.de>
---
arch/arm64/kernel/kexec_image.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/kernel/kexec_image.c b/arch/arm64/kernel/kexec_image.c
index 1fbf2ee7c005..3dee7b2d8336 100644
--- a/arch/arm64/kernel/kexec_image.c
+++ b/arch/arm64/kernel/kexec_image.c
@@ -133,9 +133,17 @@ static void *image_load(struct kimage *image,
#ifdef CONFIG_KEXEC_IMAGE_VERIFY_SIG
static int image_verify_sig(const char *kernel, unsigned long kernel_len)
{
- return verify_pefile_signature(kernel, kernel_len,
- VERIFY_USE_SECONDARY_KEYRING,
- VERIFYING_KEXEC_PE_SIGNATURE);
+ int ret;
+
+ ret = verify_pefile_signature(kernel, kernel_len,
+ VERIFY_USE_SECONDARY_KEYRING,
+ VERIFYING_KEXEC_PE_SIGNATURE);
+ if (ret == -ENOKEY && IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING)) {
+ ret = verify_pefile_signature(kernel, kernel_len,
+ VERIFY_USE_PLATFORM_KEYRING,
+ VERIFYING_KEXEC_PE_SIGNATURE);
+ }
+ return ret;
}
#endif
--
2.31.1
^ permalink raw reply related
* [PATCH 1/4] Fix arm64 kexec forbidding kernels signed with keys in the secondary keyring to boot
From: Michal Suchanek @ 2022-02-15 19:39 UTC (permalink / raw)
Cc: Michal Suchanek, Catalin Marinas, Will Deacon, Heiko Carstens,
Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
Sven Schnelle, Philipp Rudo, Baoquan He, Alexander Egorenkov,
AKASHI Takahiro, James Morse, Dave Young, Mimi Zohar, Kairui Song,
Martin Schwidefsky, linux-arm-kernel, linux-kernel, linux-s390,
kexec, keyrings, linux-security-module, stable
In-Reply-To: <cover.1644953683.git.msuchanek@suse.de>
commit d3bfe84129f6 ("certs: Add a secondary system keyring that can be added to dynamically")
split of .system_keyring into .builtin_trusted_keys and
.secondary_trusted_keys broke kexec, thereby preventing kernels signed by
keys which are now in the secondary keyring from being kexec'd.
Fix this by passing VERIFY_USE_SECONDARY_KEYRING to
verify_pefile_signature().
Cherry-picked from
commit ea93102f3224 ("Fix kexec forbidding kernels signed with keys in the secondary keyring to boot")
Fixes: 732b7b93d849 ("arm64: kexec_file: add kernel signature verification support")
Cc: kexec@lists.infradead.org
Cc: keyrings@vger.kernel.org
Cc: linux-security-module@vger.kernel.org
Cc: stable@kernel.org
Signed-off-by: Michal Suchanek <msuchanek@suse.de>
---
arch/arm64/kernel/kexec_image.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/kexec_image.c b/arch/arm64/kernel/kexec_image.c
index 9ec34690e255..1fbf2ee7c005 100644
--- a/arch/arm64/kernel/kexec_image.c
+++ b/arch/arm64/kernel/kexec_image.c
@@ -133,7 +133,8 @@ static void *image_load(struct kimage *image,
#ifdef CONFIG_KEXEC_IMAGE_VERIFY_SIG
static int image_verify_sig(const char *kernel, unsigned long kernel_len)
{
- return verify_pefile_signature(kernel, kernel_len, NULL,
+ return verify_pefile_signature(kernel, kernel_len,
+ VERIFY_USE_SECONDARY_KEYRING,
VERIFYING_KEXEC_PE_SIGNATURE);
}
#endif
--
2.31.1
^ permalink raw reply related
* Re: [PATCH] KEYS: remove support for asym_tpm keys
From: Jarkko Sakkinen @ 2022-02-15 19:30 UTC (permalink / raw)
To: Eric Biggers
Cc: David Howells, keyrings, linux-crypto, linux-security-module,
linux-kernel, Denis Kenzior, James Morris, Marcel Holtmann
In-Reply-To: <20220128195655.45342-1-ebiggers@kernel.org>
On Fri, Jan 28, 2022 at 11:56:55AM -0800, Eric Biggers wrote:
> From: Eric Biggers <ebiggers@google.com>
>
> asym_tpm keys are tied to TPM v1.2, which uses outdated crypto and has
> been deprecated in favor of TPM v2.0 for over 7 years. A very quick
> look at this code also immediately found some memory safety bugs
> (https://lore.kernel.org/r/20220113235440.90439-2-ebiggers@kernel.org).
> Note that this code is reachable by unprivileged users.
>
> According to Jarkko (one of the keyrings subsystem maintainers), this
> code has no practical use cases, and he isn't willing to maintain it
> (https://lore.kernel.org/r/YfFZPbKkgYJGWu1Q@iki.fi).
>
> Therefore, let's remove it.
>
> Note that this feature didn't have any documentation or tests, so we
> don't need to worry about removing those.
>
> Cc: David Howells <dhowells@redhat.com>
> Cc: Denis Kenzior <denkenz@gmail.com>
> Cc: James Morris <jmorris@namei.org>
> Cc: Jarkko Sakkinen <jarkko@kernel.org>
> Cc: Marcel Holtmann <marcel@holtmann.org>
> Signed-off-by: Eric Biggers <ebiggers@google.com>
> ---
> crypto/asymmetric_keys/Kconfig | 21 -
> crypto/asymmetric_keys/Makefile | 12 -
> crypto/asymmetric_keys/asym_tpm.c | 957 ----------------------------
> crypto/asymmetric_keys/tpm.asn1 | 5 -
> crypto/asymmetric_keys/tpm_parser.c | 102 ---
> include/crypto/asym_tpm_subtype.h | 19 -
> 6 files changed, 1116 deletions(-)
> delete mode 100644 crypto/asymmetric_keys/asym_tpm.c
> delete mode 100644 crypto/asymmetric_keys/tpm.asn1
> delete mode 100644 crypto/asymmetric_keys/tpm_parser.c
> delete mode 100644 include/crypto/asym_tpm_subtype.h
>
> diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
> index 1f1f004dc7577..460bc5d0a828c 100644
> --- a/crypto/asymmetric_keys/Kconfig
> +++ b/crypto/asymmetric_keys/Kconfig
> @@ -22,18 +22,6 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
> appropriate hash algorithms (such as SHA-1) must be available.
> ENOPKG will be reported if the requisite algorithm is unavailable.
>
> -config ASYMMETRIC_TPM_KEY_SUBTYPE
> - tristate "Asymmetric TPM backed private key subtype"
> - depends on TCG_TPM
> - depends on TRUSTED_KEYS
> - select CRYPTO_HMAC
> - select CRYPTO_SHA1
> - select CRYPTO_HASH_INFO
> - help
> - This option provides support for TPM backed private key type handling.
> - Operations such as sign, verify, encrypt, decrypt are performed by
> - the TPM after the private key is loaded.
> -
> config X509_CERTIFICATE_PARSER
> tristate "X.509 certificate parser"
> depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE
> @@ -54,15 +42,6 @@ config PKCS8_PRIVATE_KEY_PARSER
> private key data and provides the ability to instantiate a crypto key
> from that data.
>
> -config TPM_KEY_PARSER
> - tristate "TPM private key parser"
> - depends on ASYMMETRIC_TPM_KEY_SUBTYPE
> - select ASN1
> - help
> - This option provides support for parsing TPM format blobs for
> - private key data and provides the ability to instantiate a crypto key
> - from that data.
> -
> config PKCS7_MESSAGE_PARSER
> tristate "PKCS#7 message parser"
> depends on X509_CERTIFICATE_PARSER
> diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
> index 28b91adba2aed..c38424f55b08d 100644
> --- a/crypto/asymmetric_keys/Makefile
> +++ b/crypto/asymmetric_keys/Makefile
> @@ -11,7 +11,6 @@ asymmetric_keys-y := \
> signature.o
>
> obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o
> -obj-$(CONFIG_ASYMMETRIC_TPM_KEY_SUBTYPE) += asym_tpm.o
>
> #
> # X.509 Certificate handling
> @@ -75,14 +74,3 @@ verify_signed_pefile-y := \
>
> $(obj)/mscode_parser.o: $(obj)/mscode.asn1.h $(obj)/mscode.asn1.h
> $(obj)/mscode.asn1.o: $(obj)/mscode.asn1.c $(obj)/mscode.asn1.h
> -
> -#
> -# TPM private key parsing
> -#
> -obj-$(CONFIG_TPM_KEY_PARSER) += tpm_key_parser.o
> -tpm_key_parser-y := \
> - tpm.asn1.o \
> - tpm_parser.o
> -
> -$(obj)/tpm_parser.o: $(obj)/tpm.asn1.h
> -$(obj)/tpm.asn1.o: $(obj)/tpm.asn1.c $(obj)/tpm.asn1.h
> diff --git a/crypto/asymmetric_keys/asym_tpm.c b/crypto/asymmetric_keys/asym_tpm.c
> deleted file mode 100644
> index 0959613560b9e..0000000000000
> --- a/crypto/asymmetric_keys/asym_tpm.c
> +++ /dev/null
> @@ -1,957 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0
> -#define pr_fmt(fmt) "ASYM-TPM: "fmt
> -#include <linux/slab.h>
> -#include <linux/module.h>
> -#include <linux/export.h>
> -#include <linux/kernel.h>
> -#include <linux/seq_file.h>
> -#include <linux/scatterlist.h>
> -#include <linux/tpm.h>
> -#include <linux/tpm_command.h>
> -#include <crypto/akcipher.h>
> -#include <crypto/hash.h>
> -#include <crypto/sha1.h>
> -#include <asm/unaligned.h>
> -#include <keys/asymmetric-subtype.h>
> -#include <keys/trusted_tpm.h>
> -#include <crypto/asym_tpm_subtype.h>
> -#include <crypto/public_key.h>
> -
> -#define TPM_ORD_FLUSHSPECIFIC 186
> -#define TPM_ORD_LOADKEY2 65
> -#define TPM_ORD_UNBIND 30
> -#define TPM_ORD_SIGN 60
> -
> -#define TPM_RT_KEY 0x00000001
> -
> -/*
> - * Load a TPM key from the blob provided by userspace
> - */
> -static int tpm_loadkey2(struct tpm_buf *tb,
> - uint32_t keyhandle, unsigned char *keyauth,
> - const unsigned char *keyblob, int keybloblen,
> - uint32_t *newhandle)
> -{
> - unsigned char nonceodd[TPM_NONCE_SIZE];
> - unsigned char enonce[TPM_NONCE_SIZE];
> - unsigned char authdata[SHA1_DIGEST_SIZE];
> - uint32_t authhandle = 0;
> - unsigned char cont = 0;
> - uint32_t ordinal;
> - int ret;
> -
> - ordinal = htonl(TPM_ORD_LOADKEY2);
> -
> - /* session for loading the key */
> - ret = oiap(tb, &authhandle, enonce);
> - if (ret < 0) {
> - pr_info("oiap failed (%d)\n", ret);
> - return ret;
> - }
> -
> - /* generate odd nonce */
> - ret = tpm_get_random(NULL, nonceodd, TPM_NONCE_SIZE);
> - if (ret < 0) {
> - pr_info("tpm_get_random failed (%d)\n", ret);
> - return ret;
> - }
> -
> - /* calculate authorization HMAC value */
> - ret = TSS_authhmac(authdata, keyauth, SHA1_DIGEST_SIZE, enonce,
> - nonceodd, cont, sizeof(uint32_t), &ordinal,
> - keybloblen, keyblob, 0, 0);
> - if (ret < 0)
> - return ret;
> -
> - /* build the request buffer */
> - tpm_buf_reset(tb, TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_LOADKEY2);
> - tpm_buf_append_u32(tb, keyhandle);
> - tpm_buf_append(tb, keyblob, keybloblen);
> - tpm_buf_append_u32(tb, authhandle);
> - tpm_buf_append(tb, nonceodd, TPM_NONCE_SIZE);
> - tpm_buf_append_u8(tb, cont);
> - tpm_buf_append(tb, authdata, SHA1_DIGEST_SIZE);
> -
> - ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE);
> - if (ret < 0) {
> - pr_info("authhmac failed (%d)\n", ret);
> - return ret;
> - }
> -
> - ret = TSS_checkhmac1(tb->data, ordinal, nonceodd, keyauth,
> - SHA1_DIGEST_SIZE, 0, 0);
> - if (ret < 0) {
> - pr_info("TSS_checkhmac1 failed (%d)\n", ret);
> - return ret;
> - }
> -
> - *newhandle = LOAD32(tb->data, TPM_DATA_OFFSET);
> - return 0;
> -}
> -
> -/*
> - * Execute the FlushSpecific TPM command
> - */
> -static int tpm_flushspecific(struct tpm_buf *tb, uint32_t handle)
> -{
> - tpm_buf_reset(tb, TPM_TAG_RQU_COMMAND, TPM_ORD_FLUSHSPECIFIC);
> - tpm_buf_append_u32(tb, handle);
> - tpm_buf_append_u32(tb, TPM_RT_KEY);
> -
> - return trusted_tpm_send(tb->data, MAX_BUF_SIZE);
> -}
> -
> -/*
> - * Decrypt a blob provided by userspace using a specific key handle.
> - * The handle is a well known handle or previously loaded by e.g. LoadKey2
> - */
> -static int tpm_unbind(struct tpm_buf *tb,
> - uint32_t keyhandle, unsigned char *keyauth,
> - const unsigned char *blob, uint32_t bloblen,
> - void *out, uint32_t outlen)
> -{
> - unsigned char nonceodd[TPM_NONCE_SIZE];
> - unsigned char enonce[TPM_NONCE_SIZE];
> - unsigned char authdata[SHA1_DIGEST_SIZE];
> - uint32_t authhandle = 0;
> - unsigned char cont = 0;
> - uint32_t ordinal;
> - uint32_t datalen;
> - int ret;
> -
> - ordinal = htonl(TPM_ORD_UNBIND);
> - datalen = htonl(bloblen);
> -
> - /* session for loading the key */
> - ret = oiap(tb, &authhandle, enonce);
> - if (ret < 0) {
> - pr_info("oiap failed (%d)\n", ret);
> - return ret;
> - }
> -
> - /* generate odd nonce */
> - ret = tpm_get_random(NULL, nonceodd, TPM_NONCE_SIZE);
> - if (ret < 0) {
> - pr_info("tpm_get_random failed (%d)\n", ret);
> - return ret;
> - }
> -
> - /* calculate authorization HMAC value */
> - ret = TSS_authhmac(authdata, keyauth, SHA1_DIGEST_SIZE, enonce,
> - nonceodd, cont, sizeof(uint32_t), &ordinal,
> - sizeof(uint32_t), &datalen,
> - bloblen, blob, 0, 0);
> - if (ret < 0)
> - return ret;
> -
> - /* build the request buffer */
> - tpm_buf_reset(tb, TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_UNBIND);
> - tpm_buf_append_u32(tb, keyhandle);
> - tpm_buf_append_u32(tb, bloblen);
> - tpm_buf_append(tb, blob, bloblen);
> - tpm_buf_append_u32(tb, authhandle);
> - tpm_buf_append(tb, nonceodd, TPM_NONCE_SIZE);
> - tpm_buf_append_u8(tb, cont);
> - tpm_buf_append(tb, authdata, SHA1_DIGEST_SIZE);
> -
> - ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE);
> - if (ret < 0) {
> - pr_info("authhmac failed (%d)\n", ret);
> - return ret;
> - }
> -
> - datalen = LOAD32(tb->data, TPM_DATA_OFFSET);
> -
> - ret = TSS_checkhmac1(tb->data, ordinal, nonceodd,
> - keyauth, SHA1_DIGEST_SIZE,
> - sizeof(uint32_t), TPM_DATA_OFFSET,
> - datalen, TPM_DATA_OFFSET + sizeof(uint32_t),
> - 0, 0);
> - if (ret < 0) {
> - pr_info("TSS_checkhmac1 failed (%d)\n", ret);
> - return ret;
> - }
> -
> - memcpy(out, tb->data + TPM_DATA_OFFSET + sizeof(uint32_t),
> - min(outlen, datalen));
> -
> - return datalen;
> -}
> -
> -/*
> - * Sign a blob provided by userspace (that has had the hash function applied)
> - * using a specific key handle. The handle is assumed to have been previously
> - * loaded by e.g. LoadKey2.
> - *
> - * Note that the key signature scheme of the used key should be set to
> - * TPM_SS_RSASSAPKCS1v15_DER. This allows the hashed input to be of any size
> - * up to key_length_in_bytes - 11 and not be limited to size 20 like the
> - * TPM_SS_RSASSAPKCS1v15_SHA1 signature scheme.
> - */
> -static int tpm_sign(struct tpm_buf *tb,
> - uint32_t keyhandle, unsigned char *keyauth,
> - const unsigned char *blob, uint32_t bloblen,
> - void *out, uint32_t outlen)
> -{
> - unsigned char nonceodd[TPM_NONCE_SIZE];
> - unsigned char enonce[TPM_NONCE_SIZE];
> - unsigned char authdata[SHA1_DIGEST_SIZE];
> - uint32_t authhandle = 0;
> - unsigned char cont = 0;
> - uint32_t ordinal;
> - uint32_t datalen;
> - int ret;
> -
> - ordinal = htonl(TPM_ORD_SIGN);
> - datalen = htonl(bloblen);
> -
> - /* session for loading the key */
> - ret = oiap(tb, &authhandle, enonce);
> - if (ret < 0) {
> - pr_info("oiap failed (%d)\n", ret);
> - return ret;
> - }
> -
> - /* generate odd nonce */
> - ret = tpm_get_random(NULL, nonceodd, TPM_NONCE_SIZE);
> - if (ret < 0) {
> - pr_info("tpm_get_random failed (%d)\n", ret);
> - return ret;
> - }
> -
> - /* calculate authorization HMAC value */
> - ret = TSS_authhmac(authdata, keyauth, SHA1_DIGEST_SIZE, enonce,
> - nonceodd, cont, sizeof(uint32_t), &ordinal,
> - sizeof(uint32_t), &datalen,
> - bloblen, blob, 0, 0);
> - if (ret < 0)
> - return ret;
> -
> - /* build the request buffer */
> - tpm_buf_reset(tb, TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_SIGN);
> - tpm_buf_append_u32(tb, keyhandle);
> - tpm_buf_append_u32(tb, bloblen);
> - tpm_buf_append(tb, blob, bloblen);
> - tpm_buf_append_u32(tb, authhandle);
> - tpm_buf_append(tb, nonceodd, TPM_NONCE_SIZE);
> - tpm_buf_append_u8(tb, cont);
> - tpm_buf_append(tb, authdata, SHA1_DIGEST_SIZE);
> -
> - ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE);
> - if (ret < 0) {
> - pr_info("authhmac failed (%d)\n", ret);
> - return ret;
> - }
> -
> - datalen = LOAD32(tb->data, TPM_DATA_OFFSET);
> -
> - ret = TSS_checkhmac1(tb->data, ordinal, nonceodd,
> - keyauth, SHA1_DIGEST_SIZE,
> - sizeof(uint32_t), TPM_DATA_OFFSET,
> - datalen, TPM_DATA_OFFSET + sizeof(uint32_t),
> - 0, 0);
> - if (ret < 0) {
> - pr_info("TSS_checkhmac1 failed (%d)\n", ret);
> - return ret;
> - }
> -
> - memcpy(out, tb->data + TPM_DATA_OFFSET + sizeof(uint32_t),
> - min(datalen, outlen));
> -
> - return datalen;
> -}
> -
> -/* Room to fit two u32 zeros for algo id and parameters length. */
> -#define SETKEY_PARAMS_SIZE (sizeof(u32) * 2)
> -
> -/*
> - * Maximum buffer size for the BER/DER encoded public key. The public key
> - * is of the form SEQUENCE { INTEGER n, INTEGER e } where n is a maximum 2048
> - * bit key and e is usually 65537
> - * The encoding overhead is:
> - * - max 4 bytes for SEQUENCE
> - * - max 4 bytes for INTEGER n type/length
> - * - 257 bytes of n
> - * - max 2 bytes for INTEGER e type/length
> - * - 3 bytes of e
> - * - 4+4 of zeros for set_pub_key parameters (SETKEY_PARAMS_SIZE)
> - */
> -#define PUB_KEY_BUF_SIZE (4 + 4 + 257 + 2 + 3 + SETKEY_PARAMS_SIZE)
> -
> -/*
> - * Provide a part of a description of the key for /proc/keys.
> - */
> -static void asym_tpm_describe(const struct key *asymmetric_key,
> - struct seq_file *m)
> -{
> - struct tpm_key *tk = asymmetric_key->payload.data[asym_crypto];
> -
> - if (!tk)
> - return;
> -
> - seq_printf(m, "TPM1.2/Blob");
> -}
> -
> -static void asym_tpm_destroy(void *payload0, void *payload3)
> -{
> - struct tpm_key *tk = payload0;
> -
> - if (!tk)
> - return;
> -
> - kfree(tk->blob);
> - tk->blob_len = 0;
> -
> - kfree(tk);
> -}
> -
> -/* How many bytes will it take to encode the length */
> -static inline uint32_t definite_length(uint32_t len)
> -{
> - if (len <= 127)
> - return 1;
> - if (len <= 255)
> - return 2;
> - return 3;
> -}
> -
> -static inline uint8_t *encode_tag_length(uint8_t *buf, uint8_t tag,
> - uint32_t len)
> -{
> - *buf++ = tag;
> -
> - if (len <= 127) {
> - buf[0] = len;
> - return buf + 1;
> - }
> -
> - if (len <= 255) {
> - buf[0] = 0x81;
> - buf[1] = len;
> - return buf + 2;
> - }
> -
> - buf[0] = 0x82;
> - put_unaligned_be16(len, buf + 1);
> - return buf + 3;
> -}
> -
> -static uint32_t derive_pub_key(const void *pub_key, uint32_t len, uint8_t *buf)
> -{
> - uint8_t *cur = buf;
> - uint32_t n_len = definite_length(len) + 1 + len + 1;
> - uint32_t e_len = definite_length(3) + 1 + 3;
> - uint8_t e[3] = { 0x01, 0x00, 0x01 };
> -
> - /* SEQUENCE */
> - cur = encode_tag_length(cur, 0x30, n_len + e_len);
> - /* INTEGER n */
> - cur = encode_tag_length(cur, 0x02, len + 1);
> - cur[0] = 0x00;
> - memcpy(cur + 1, pub_key, len);
> - cur += len + 1;
> - cur = encode_tag_length(cur, 0x02, sizeof(e));
> - memcpy(cur, e, sizeof(e));
> - cur += sizeof(e);
> - /* Zero parameters to satisfy set_pub_key ABI. */
> - memzero_explicit(cur, SETKEY_PARAMS_SIZE);
> -
> - return cur - buf;
> -}
> -
> -/*
> - * Determine the crypto algorithm name.
> - */
> -static int determine_akcipher(const char *encoding, const char *hash_algo,
> - char alg_name[CRYPTO_MAX_ALG_NAME])
> -{
> - if (strcmp(encoding, "pkcs1") == 0) {
> - if (!hash_algo) {
> - strcpy(alg_name, "pkcs1pad(rsa)");
> - return 0;
> - }
> -
> - if (snprintf(alg_name, CRYPTO_MAX_ALG_NAME, "pkcs1pad(rsa,%s)",
> - hash_algo) >= CRYPTO_MAX_ALG_NAME)
> - return -EINVAL;
> -
> - return 0;
> - }
> -
> - if (strcmp(encoding, "raw") == 0) {
> - strcpy(alg_name, "rsa");
> - return 0;
> - }
> -
> - return -ENOPKG;
> -}
> -
> -/*
> - * Query information about a key.
> - */
> -static int tpm_key_query(const struct kernel_pkey_params *params,
> - struct kernel_pkey_query *info)
> -{
> - struct tpm_key *tk = params->key->payload.data[asym_crypto];
> - int ret;
> - char alg_name[CRYPTO_MAX_ALG_NAME];
> - struct crypto_akcipher *tfm;
> - uint8_t der_pub_key[PUB_KEY_BUF_SIZE];
> - uint32_t der_pub_key_len;
> - int len;
> -
> - /* TPM only works on private keys, public keys still done in software */
> - ret = determine_akcipher(params->encoding, params->hash_algo, alg_name);
> - if (ret < 0)
> - return ret;
> -
> - tfm = crypto_alloc_akcipher(alg_name, 0, 0);
> - if (IS_ERR(tfm))
> - return PTR_ERR(tfm);
> -
> - der_pub_key_len = derive_pub_key(tk->pub_key, tk->pub_key_len,
> - der_pub_key);
> -
> - ret = crypto_akcipher_set_pub_key(tfm, der_pub_key, der_pub_key_len);
> - if (ret < 0)
> - goto error_free_tfm;
> -
> - len = crypto_akcipher_maxsize(tfm);
> -
> - info->key_size = tk->key_len;
> - info->max_data_size = tk->key_len / 8;
> - info->max_sig_size = len;
> - info->max_enc_size = len;
> - info->max_dec_size = tk->key_len / 8;
> -
> - info->supported_ops = KEYCTL_SUPPORTS_ENCRYPT |
> - KEYCTL_SUPPORTS_DECRYPT |
> - KEYCTL_SUPPORTS_VERIFY |
> - KEYCTL_SUPPORTS_SIGN;
> -
> - ret = 0;
> -error_free_tfm:
> - crypto_free_akcipher(tfm);
> - pr_devel("<==%s() = %d\n", __func__, ret);
> - return ret;
> -}
> -
> -/*
> - * Encryption operation is performed with the public key. Hence it is done
> - * in software
> - */
> -static int tpm_key_encrypt(struct tpm_key *tk,
> - struct kernel_pkey_params *params,
> - const void *in, void *out)
> -{
> - char alg_name[CRYPTO_MAX_ALG_NAME];
> - struct crypto_akcipher *tfm;
> - struct akcipher_request *req;
> - struct crypto_wait cwait;
> - struct scatterlist in_sg, out_sg;
> - uint8_t der_pub_key[PUB_KEY_BUF_SIZE];
> - uint32_t der_pub_key_len;
> - int ret;
> -
> - pr_devel("==>%s()\n", __func__);
> -
> - ret = determine_akcipher(params->encoding, params->hash_algo, alg_name);
> - if (ret < 0)
> - return ret;
> -
> - tfm = crypto_alloc_akcipher(alg_name, 0, 0);
> - if (IS_ERR(tfm))
> - return PTR_ERR(tfm);
> -
> - der_pub_key_len = derive_pub_key(tk->pub_key, tk->pub_key_len,
> - der_pub_key);
> -
> - ret = crypto_akcipher_set_pub_key(tfm, der_pub_key, der_pub_key_len);
> - if (ret < 0)
> - goto error_free_tfm;
> -
> - ret = -ENOMEM;
> - req = akcipher_request_alloc(tfm, GFP_KERNEL);
> - if (!req)
> - goto error_free_tfm;
> -
> - sg_init_one(&in_sg, in, params->in_len);
> - sg_init_one(&out_sg, out, params->out_len);
> - akcipher_request_set_crypt(req, &in_sg, &out_sg, params->in_len,
> - params->out_len);
> - crypto_init_wait(&cwait);
> - akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
> - CRYPTO_TFM_REQ_MAY_SLEEP,
> - crypto_req_done, &cwait);
> -
> - ret = crypto_akcipher_encrypt(req);
> - ret = crypto_wait_req(ret, &cwait);
> -
> - if (ret == 0)
> - ret = req->dst_len;
> -
> - akcipher_request_free(req);
> -error_free_tfm:
> - crypto_free_akcipher(tfm);
> - pr_devel("<==%s() = %d\n", __func__, ret);
> - return ret;
> -}
> -
> -/*
> - * Decryption operation is performed with the private key in the TPM.
> - */
> -static int tpm_key_decrypt(struct tpm_key *tk,
> - struct kernel_pkey_params *params,
> - const void *in, void *out)
> -{
> - struct tpm_buf tb;
> - uint32_t keyhandle;
> - uint8_t srkauth[SHA1_DIGEST_SIZE];
> - uint8_t keyauth[SHA1_DIGEST_SIZE];
> - int r;
> -
> - pr_devel("==>%s()\n", __func__);
> -
> - if (params->hash_algo)
> - return -ENOPKG;
> -
> - if (strcmp(params->encoding, "pkcs1"))
> - return -ENOPKG;
> -
> - r = tpm_buf_init(&tb, 0, 0);
> - if (r)
> - return r;
> -
> - /* TODO: Handle a non-all zero SRK authorization */
> - memset(srkauth, 0, sizeof(srkauth));
> -
> - r = tpm_loadkey2(&tb, SRKHANDLE, srkauth,
> - tk->blob, tk->blob_len, &keyhandle);
> - if (r < 0) {
> - pr_devel("loadkey2 failed (%d)\n", r);
> - goto error;
> - }
> -
> - /* TODO: Handle a non-all zero key authorization */
> - memset(keyauth, 0, sizeof(keyauth));
> -
> - r = tpm_unbind(&tb, keyhandle, keyauth,
> - in, params->in_len, out, params->out_len);
> - if (r < 0)
> - pr_devel("tpm_unbind failed (%d)\n", r);
> -
> - if (tpm_flushspecific(&tb, keyhandle) < 0)
> - pr_devel("flushspecific failed (%d)\n", r);
> -
> -error:
> - tpm_buf_destroy(&tb);
> - pr_devel("<==%s() = %d\n", __func__, r);
> - return r;
> -}
> -
> -/*
> - * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2].
> - */
> -static const u8 digest_info_md5[] = {
> - 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,
> - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, /* OID */
> - 0x05, 0x00, 0x04, 0x10
> -};
> -
> -static const u8 digest_info_sha1[] = {
> - 0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
> - 0x2b, 0x0e, 0x03, 0x02, 0x1a,
> - 0x05, 0x00, 0x04, 0x14
> -};
> -
> -static const u8 digest_info_rmd160[] = {
> - 0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
> - 0x2b, 0x24, 0x03, 0x02, 0x01,
> - 0x05, 0x00, 0x04, 0x14
> -};
> -
> -static const u8 digest_info_sha224[] = {
> - 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
> - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
> - 0x05, 0x00, 0x04, 0x1c
> -};
> -
> -static const u8 digest_info_sha256[] = {
> - 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
> - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
> - 0x05, 0x00, 0x04, 0x20
> -};
> -
> -static const u8 digest_info_sha384[] = {
> - 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
> - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
> - 0x05, 0x00, 0x04, 0x30
> -};
> -
> -static const u8 digest_info_sha512[] = {
> - 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
> - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
> - 0x05, 0x00, 0x04, 0x40
> -};
> -
> -static const struct asn1_template {
> - const char *name;
> - const u8 *data;
> - size_t size;
> -} asn1_templates[] = {
> -#define _(X) { #X, digest_info_##X, sizeof(digest_info_##X) }
> - _(md5),
> - _(sha1),
> - _(rmd160),
> - _(sha256),
> - _(sha384),
> - _(sha512),
> - _(sha224),
> - { NULL }
> -#undef _
> -};
> -
> -static const struct asn1_template *lookup_asn1(const char *name)
> -{
> - const struct asn1_template *p;
> -
> - for (p = asn1_templates; p->name; p++)
> - if (strcmp(name, p->name) == 0)
> - return p;
> - return NULL;
> -}
> -
> -/*
> - * Sign operation is performed with the private key in the TPM.
> - */
> -static int tpm_key_sign(struct tpm_key *tk,
> - struct kernel_pkey_params *params,
> - const void *in, void *out)
> -{
> - struct tpm_buf tb;
> - uint32_t keyhandle;
> - uint8_t srkauth[SHA1_DIGEST_SIZE];
> - uint8_t keyauth[SHA1_DIGEST_SIZE];
> - void *asn1_wrapped = NULL;
> - uint32_t in_len = params->in_len;
> - int r;
> -
> - pr_devel("==>%s()\n", __func__);
> -
> - if (strcmp(params->encoding, "pkcs1"))
> - return -ENOPKG;
> -
> - if (params->hash_algo) {
> - const struct asn1_template *asn1 =
> - lookup_asn1(params->hash_algo);
> -
> - if (!asn1)
> - return -ENOPKG;
> -
> - /* request enough space for the ASN.1 template + input hash */
> - asn1_wrapped = kzalloc(in_len + asn1->size, GFP_KERNEL);
> - if (!asn1_wrapped)
> - return -ENOMEM;
> -
> - /* Copy ASN.1 template, then the input */
> - memcpy(asn1_wrapped, asn1->data, asn1->size);
> - memcpy(asn1_wrapped + asn1->size, in, in_len);
> -
> - in = asn1_wrapped;
> - in_len += asn1->size;
> - }
> -
> - if (in_len > tk->key_len / 8 - 11) {
> - r = -EOVERFLOW;
> - goto error_free_asn1_wrapped;
> - }
> -
> - r = tpm_buf_init(&tb, 0, 0);
> - if (r)
> - goto error_free_asn1_wrapped;
> -
> - /* TODO: Handle a non-all zero SRK authorization */
> - memset(srkauth, 0, sizeof(srkauth));
> -
> - r = tpm_loadkey2(&tb, SRKHANDLE, srkauth,
> - tk->blob, tk->blob_len, &keyhandle);
> - if (r < 0) {
> - pr_devel("loadkey2 failed (%d)\n", r);
> - goto error_free_tb;
> - }
> -
> - /* TODO: Handle a non-all zero key authorization */
> - memset(keyauth, 0, sizeof(keyauth));
> -
> - r = tpm_sign(&tb, keyhandle, keyauth, in, in_len, out, params->out_len);
> - if (r < 0)
> - pr_devel("tpm_sign failed (%d)\n", r);
> -
> - if (tpm_flushspecific(&tb, keyhandle) < 0)
> - pr_devel("flushspecific failed (%d)\n", r);
> -
> -error_free_tb:
> - tpm_buf_destroy(&tb);
> -error_free_asn1_wrapped:
> - kfree(asn1_wrapped);
> - pr_devel("<==%s() = %d\n", __func__, r);
> - return r;
> -}
> -
> -/*
> - * Do encryption, decryption and signing ops.
> - */
> -static int tpm_key_eds_op(struct kernel_pkey_params *params,
> - const void *in, void *out)
> -{
> - struct tpm_key *tk = params->key->payload.data[asym_crypto];
> - int ret = -EOPNOTSUPP;
> -
> - /* Perform the encryption calculation. */
> - switch (params->op) {
> - case kernel_pkey_encrypt:
> - ret = tpm_key_encrypt(tk, params, in, out);
> - break;
> - case kernel_pkey_decrypt:
> - ret = tpm_key_decrypt(tk, params, in, out);
> - break;
> - case kernel_pkey_sign:
> - ret = tpm_key_sign(tk, params, in, out);
> - break;
> - default:
> - BUG();
> - }
> -
> - return ret;
> -}
> -
> -/*
> - * Verify a signature using a public key.
> - */
> -static int tpm_key_verify_signature(const struct key *key,
> - const struct public_key_signature *sig)
> -{
> - const struct tpm_key *tk = key->payload.data[asym_crypto];
> - struct crypto_wait cwait;
> - struct crypto_akcipher *tfm;
> - struct akcipher_request *req;
> - struct scatterlist src_sg[2];
> - char alg_name[CRYPTO_MAX_ALG_NAME];
> - uint8_t der_pub_key[PUB_KEY_BUF_SIZE];
> - uint32_t der_pub_key_len;
> - int ret;
> -
> - pr_devel("==>%s()\n", __func__);
> -
> - BUG_ON(!tk);
> - BUG_ON(!sig);
> - BUG_ON(!sig->s);
> -
> - if (!sig->digest)
> - return -ENOPKG;
> -
> - ret = determine_akcipher(sig->encoding, sig->hash_algo, alg_name);
> - if (ret < 0)
> - return ret;
> -
> - tfm = crypto_alloc_akcipher(alg_name, 0, 0);
> - if (IS_ERR(tfm))
> - return PTR_ERR(tfm);
> -
> - der_pub_key_len = derive_pub_key(tk->pub_key, tk->pub_key_len,
> - der_pub_key);
> -
> - ret = crypto_akcipher_set_pub_key(tfm, der_pub_key, der_pub_key_len);
> - if (ret < 0)
> - goto error_free_tfm;
> -
> - ret = -ENOMEM;
> - req = akcipher_request_alloc(tfm, GFP_KERNEL);
> - if (!req)
> - goto error_free_tfm;
> -
> - sg_init_table(src_sg, 2);
> - sg_set_buf(&src_sg[0], sig->s, sig->s_size);
> - sg_set_buf(&src_sg[1], sig->digest, sig->digest_size);
> - akcipher_request_set_crypt(req, src_sg, NULL, sig->s_size,
> - sig->digest_size);
> - crypto_init_wait(&cwait);
> - akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
> - CRYPTO_TFM_REQ_MAY_SLEEP,
> - crypto_req_done, &cwait);
> - ret = crypto_wait_req(crypto_akcipher_verify(req), &cwait);
> -
> - akcipher_request_free(req);
> -error_free_tfm:
> - crypto_free_akcipher(tfm);
> - pr_devel("<==%s() = %d\n", __func__, ret);
> - if (WARN_ON_ONCE(ret > 0))
> - ret = -EINVAL;
> - return ret;
> -}
> -
> -/*
> - * Parse enough information out of TPM_KEY structure:
> - * TPM_STRUCT_VER -> 4 bytes
> - * TPM_KEY_USAGE -> 2 bytes
> - * TPM_KEY_FLAGS -> 4 bytes
> - * TPM_AUTH_DATA_USAGE -> 1 byte
> - * TPM_KEY_PARMS -> variable
> - * UINT32 PCRInfoSize -> 4 bytes
> - * BYTE* -> PCRInfoSize bytes
> - * TPM_STORE_PUBKEY
> - * UINT32 encDataSize;
> - * BYTE* -> encDataSize;
> - *
> - * TPM_KEY_PARMS:
> - * TPM_ALGORITHM_ID -> 4 bytes
> - * TPM_ENC_SCHEME -> 2 bytes
> - * TPM_SIG_SCHEME -> 2 bytes
> - * UINT32 parmSize -> 4 bytes
> - * BYTE* -> variable
> - */
> -static int extract_key_parameters(struct tpm_key *tk)
> -{
> - const void *cur = tk->blob;
> - uint32_t len = tk->blob_len;
> - const void *pub_key;
> - uint32_t sz;
> - uint32_t key_len;
> -
> - if (len < 11)
> - return -EBADMSG;
> -
> - /* Ensure this is a legacy key */
> - if (get_unaligned_be16(cur + 4) != 0x0015)
> - return -EBADMSG;
> -
> - /* Skip to TPM_KEY_PARMS */
> - cur += 11;
> - len -= 11;
> -
> - if (len < 12)
> - return -EBADMSG;
> -
> - /* Make sure this is an RSA key */
> - if (get_unaligned_be32(cur) != 0x00000001)
> - return -EBADMSG;
> -
> - /* Make sure this is TPM_ES_RSAESPKCSv15 encoding scheme */
> - if (get_unaligned_be16(cur + 4) != 0x0002)
> - return -EBADMSG;
> -
> - /* Make sure this is TPM_SS_RSASSAPKCS1v15_DER signature scheme */
> - if (get_unaligned_be16(cur + 6) != 0x0003)
> - return -EBADMSG;
> -
> - sz = get_unaligned_be32(cur + 8);
> - if (len < sz + 12)
> - return -EBADMSG;
> -
> - /* Move to TPM_RSA_KEY_PARMS */
> - len -= 12;
> - cur += 12;
> -
> - /* Grab the RSA key length */
> - key_len = get_unaligned_be32(cur);
> -
> - switch (key_len) {
> - case 512:
> - case 1024:
> - case 1536:
> - case 2048:
> - break;
> - default:
> - return -EINVAL;
> - }
> -
> - /* Move just past TPM_KEY_PARMS */
> - cur += sz;
> - len -= sz;
> -
> - if (len < 4)
> - return -EBADMSG;
> -
> - sz = get_unaligned_be32(cur);
> - if (len < 4 + sz)
> - return -EBADMSG;
> -
> - /* Move to TPM_STORE_PUBKEY */
> - cur += 4 + sz;
> - len -= 4 + sz;
> -
> - /* Grab the size of the public key, it should jive with the key size */
> - sz = get_unaligned_be32(cur);
> - if (sz > 256)
> - return -EINVAL;
> -
> - pub_key = cur + 4;
> -
> - tk->key_len = key_len;
> - tk->pub_key = pub_key;
> - tk->pub_key_len = sz;
> -
> - return 0;
> -}
> -
> -/* Given the blob, parse it and load it into the TPM */
> -struct tpm_key *tpm_key_create(const void *blob, uint32_t blob_len)
> -{
> - int r;
> - struct tpm_key *tk;
> -
> - r = tpm_is_tpm2(NULL);
> - if (r < 0)
> - goto error;
> -
> - /* We don't support TPM2 yet */
> - if (r > 0) {
> - r = -ENODEV;
> - goto error;
> - }
> -
> - r = -ENOMEM;
> - tk = kzalloc(sizeof(struct tpm_key), GFP_KERNEL);
> - if (!tk)
> - goto error;
> -
> - tk->blob = kmemdup(blob, blob_len, GFP_KERNEL);
> - if (!tk->blob)
> - goto error_memdup;
> -
> - tk->blob_len = blob_len;
> -
> - r = extract_key_parameters(tk);
> - if (r < 0)
> - goto error_extract;
> -
> - return tk;
> -
> -error_extract:
> - kfree(tk->blob);
> - tk->blob_len = 0;
> -error_memdup:
> - kfree(tk);
> -error:
> - return ERR_PTR(r);
> -}
> -EXPORT_SYMBOL_GPL(tpm_key_create);
> -
> -/*
> - * TPM-based asymmetric key subtype
> - */
> -struct asymmetric_key_subtype asym_tpm_subtype = {
> - .owner = THIS_MODULE,
> - .name = "asym_tpm",
> - .name_len = sizeof("asym_tpm") - 1,
> - .describe = asym_tpm_describe,
> - .destroy = asym_tpm_destroy,
> - .query = tpm_key_query,
> - .eds_op = tpm_key_eds_op,
> - .verify_signature = tpm_key_verify_signature,
> -};
> -EXPORT_SYMBOL_GPL(asym_tpm_subtype);
> -
> -MODULE_DESCRIPTION("TPM based asymmetric key subtype");
> -MODULE_AUTHOR("Intel Corporation");
> -MODULE_LICENSE("GPL v2");
> diff --git a/crypto/asymmetric_keys/tpm.asn1 b/crypto/asymmetric_keys/tpm.asn1
> deleted file mode 100644
> index d7f194232f30a..0000000000000
> --- a/crypto/asymmetric_keys/tpm.asn1
> +++ /dev/null
> @@ -1,5 +0,0 @@
> ---
> --- Unencryted TPM Blob. For details of the format, see:
> --- http://david.woodhou.se/draft-woodhouse-cert-best-practice.html#I-D.mavrogiannopoulos-tpmuri
> ---
> -PrivateKeyInfo ::= OCTET STRING ({ tpm_note_key })
> diff --git a/crypto/asymmetric_keys/tpm_parser.c b/crypto/asymmetric_keys/tpm_parser.c
> deleted file mode 100644
> index 96405d8dcd98d..0000000000000
> --- a/crypto/asymmetric_keys/tpm_parser.c
> +++ /dev/null
> @@ -1,102 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0
> -#define pr_fmt(fmt) "TPM-PARSER: "fmt
> -#include <linux/module.h>
> -#include <linux/kernel.h>
> -#include <linux/export.h>
> -#include <linux/slab.h>
> -#include <linux/err.h>
> -#include <keys/asymmetric-subtype.h>
> -#include <keys/asymmetric-parser.h>
> -#include <crypto/asym_tpm_subtype.h>
> -#include "tpm.asn1.h"
> -
> -struct tpm_parse_context {
> - const void *blob;
> - u32 blob_len;
> -};
> -
> -/*
> - * Note the key data of the ASN.1 blob.
> - */
> -int tpm_note_key(void *context, size_t hdrlen,
> - unsigned char tag,
> - const void *value, size_t vlen)
> -{
> - struct tpm_parse_context *ctx = context;
> -
> - ctx->blob = value;
> - ctx->blob_len = vlen;
> -
> - return 0;
> -}
> -
> -/*
> - * Parse a TPM-encrypted private key blob.
> - */
> -static struct tpm_key *tpm_parse(const void *data, size_t datalen)
> -{
> - struct tpm_parse_context ctx;
> - long ret;
> -
> - memset(&ctx, 0, sizeof(ctx));
> -
> - /* Attempt to decode the private key */
> - ret = asn1_ber_decoder(&tpm_decoder, &ctx, data, datalen);
> - if (ret < 0)
> - goto error;
> -
> - return tpm_key_create(ctx.blob, ctx.blob_len);
> -
> -error:
> - return ERR_PTR(ret);
> -}
> -/*
> - * Attempt to parse a data blob for a key as a TPM private key blob.
> - */
> -static int tpm_key_preparse(struct key_preparsed_payload *prep)
> -{
> - struct tpm_key *tk;
> -
> - /*
> - * TPM 1.2 keys are max 2048 bits long, so assume the blob is no
> - * more than 4x that
> - */
> - if (prep->datalen > 256 * 4)
> - return -EMSGSIZE;
> -
> - tk = tpm_parse(prep->data, prep->datalen);
> -
> - if (IS_ERR(tk))
> - return PTR_ERR(tk);
> -
> - /* We're pinning the module by being linked against it */
> - __module_get(asym_tpm_subtype.owner);
> - prep->payload.data[asym_subtype] = &asym_tpm_subtype;
> - prep->payload.data[asym_key_ids] = NULL;
> - prep->payload.data[asym_crypto] = tk;
> - prep->payload.data[asym_auth] = NULL;
> - prep->quotalen = 100;
> - return 0;
> -}
> -
> -static struct asymmetric_key_parser tpm_key_parser = {
> - .owner = THIS_MODULE,
> - .name = "tpm_parser",
> - .parse = tpm_key_preparse,
> -};
> -
> -static int __init tpm_key_init(void)
> -{
> - return register_asymmetric_key_parser(&tpm_key_parser);
> -}
> -
> -static void __exit tpm_key_exit(void)
> -{
> - unregister_asymmetric_key_parser(&tpm_key_parser);
> -}
> -
> -module_init(tpm_key_init);
> -module_exit(tpm_key_exit);
> -
> -MODULE_DESCRIPTION("TPM private key-blob parser");
> -MODULE_LICENSE("GPL v2");
> diff --git a/include/crypto/asym_tpm_subtype.h b/include/crypto/asym_tpm_subtype.h
> deleted file mode 100644
> index 48198c36d6b9b..0000000000000
> --- a/include/crypto/asym_tpm_subtype.h
> +++ /dev/null
> @@ -1,19 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0
> -#ifndef _LINUX_ASYM_TPM_SUBTYPE_H
> -#define _LINUX_ASYM_TPM_SUBTYPE_H
> -
> -#include <linux/keyctl.h>
> -
> -struct tpm_key {
> - void *blob;
> - u32 blob_len;
> - uint16_t key_len; /* Size in bits of the key */
> - const void *pub_key; /* pointer inside blob to the public key bytes */
> - uint16_t pub_key_len; /* length of the public key */
> -};
> -
> -struct tpm_key *tpm_key_create(const void *blob, uint32_t blob_len);
> -
> -extern struct asymmetric_key_subtype asym_tpm_subtype;
> -
> -#endif /* _LINUX_ASYM_TPM_SUBTYPE_H */
> --
> 2.35.0
>
I'm now getting back to track with kernel. Job transition is the reason for
this misserable latency.
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
This needs some acks from other people before I can apply the patch but I
strongly support it.
/Jarkko
^ permalink raw reply
* Re: [PATCH v10 03/27] ima: Return error code obtained from securityfs functions
From: Mimi Zohar @ 2022-02-15 18:09 UTC (permalink / raw)
To: Stefan Berger, linux-integrity
Cc: serge, christian.brauner, containers, dmitry.kasatkin, ebiederm,
krzysztof.struczynski, roberto.sassu, mpeters, lhinds, lsturman,
puiterwi, jejb, jamjoom, linux-kernel, paul, rgb,
linux-security-module, jmorris
In-Reply-To: <1a4bc3cf915057bc5c5957c42c164bc2491a9da7.camel@linux.ibm.com>
On Thu, 2022-02-10 at 07:02 -0500, Mimi Zohar wrote:
> On Tue, 2022-02-01 at 15:37 -0500, Stefan Berger wrote:
> > If an error occurs when creating a securityfs file, return the exact
> > error code to the caller.
> >
> > Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
>
> Thanks, Stefan. Nice cleanup.
This is now queued in next-integrity.
--
Thanks,
Mimi
^ permalink raw reply
* RE: [PATCH v2 3/6] bpf-lsm: Introduce new helper bpf_ima_file_hash()
From: Roberto Sassu @ 2022-02-15 17:04 UTC (permalink / raw)
To: Yonghong Song, zohar@linux.ibm.com, shuah@kernel.org,
ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org,
kpsingh@kernel.org, revest@chromium.org
Cc: linux-integrity@vger.kernel.org,
linux-security-module@vger.kernel.org,
linux-kselftest@vger.kernel.org, netdev@vger.kernel.org,
bpf@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <f939bd53-96d0-d1dc-306f-6215ade6a7f1@fb.com>
> From: Yonghong Song [mailto:yhs@fb.com]
> Sent: Tuesday, February 15, 2022 6:03 PM
> On 2/15/22 4:40 AM, Roberto Sassu wrote:
> > ima_file_hash() has been modified to calculate the measurement of a file on
> > demand, if it has not been already performed by IMA. For compatibility
> > reasons, ima_inode_hash() remains unchanged.
> >
> > Keep the same approach in eBPF and introduce the new helper
> > bpf_ima_file_hash() to take advantage of the modified behavior of
> > ima_file_hash().
> >
> > Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> > ---
> > include/uapi/linux/bpf.h | 11 +++++++++++
> > kernel/bpf/bpf_lsm.c | 20 ++++++++++++++++++++
> > tools/include/uapi/linux/bpf.h | 11 +++++++++++
> > 3 files changed, 42 insertions(+)
> >
> > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > index b0383d371b9a..ba33d5718d6b 100644
> > --- a/include/uapi/linux/bpf.h
> > +++ b/include/uapi/linux/bpf.h
> > @@ -4648,6 +4648,16 @@ union bpf_attr {
> > * **-EOPNOTSUP** if IMA is disabled or **-EINVAL** if
> > * invalid arguments are passed.
> > *
> > + * long bpf_ima_file_hash(struct file *file, void *dst, u32 size)
> > + * Description
> > + * Returns a calculated IMA hash of the *file*.
> > + * If the hash is larger than *size*, then only *size*
> > + * bytes will be copied to *dst*
> > + * Return
> > + * The **hash_algo** is returned on success,
> > + * **-EOPNOTSUP** if the hash calculation failed or **-EINVAL**
> if
> > + * invalid arguments are passed.
> > + *
> > * struct socket *bpf_sock_from_file(struct file *file)
> > * Description
> > * If the given file represents a socket, returns the associated
> > @@ -5182,6 +5192,7 @@ union bpf_attr {
> > FN(bprm_opts_set), \
> > FN(ktime_get_coarse_ns), \
> > FN(ima_inode_hash), \
> > + FN(ima_file_hash), \
>
> Please put the above FN(ima_file_hash) to the end of the list.
> Otherwise, we have a backward compatability issue.
Hi Yonghong
sure, will do.
Thanks
Roberto
HUAWEI TECHNOLOGIES Duesseldorf GmbH, HRB 56063
Managing Director: Li Peng, Zhong Ronghua
> > FN(sock_from_file), \
> > FN(check_mtu), \
> > FN(for_each_map_elem), \
> > diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c
> > index 9e4ecc990647..e8d27af5bbcc 100644
> > --- a/kernel/bpf/bpf_lsm.c
> > +++ b/kernel/bpf/bpf_lsm.c
> [...]
^ permalink raw reply
* Re: [PATCH v2 3/6] bpf-lsm: Introduce new helper bpf_ima_file_hash()
From: Yonghong Song @ 2022-02-15 17:02 UTC (permalink / raw)
To: Roberto Sassu, zohar, shuah, ast, daniel, andrii, kpsingh, revest
Cc: linux-integrity, linux-security-module, linux-kselftest, netdev,
bpf, linux-kernel
In-Reply-To: <20220215124042.186506-4-roberto.sassu@huawei.com>
On 2/15/22 4:40 AM, Roberto Sassu wrote:
> ima_file_hash() has been modified to calculate the measurement of a file on
> demand, if it has not been already performed by IMA. For compatibility
> reasons, ima_inode_hash() remains unchanged.
>
> Keep the same approach in eBPF and introduce the new helper
> bpf_ima_file_hash() to take advantage of the modified behavior of
> ima_file_hash().
>
> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> ---
> include/uapi/linux/bpf.h | 11 +++++++++++
> kernel/bpf/bpf_lsm.c | 20 ++++++++++++++++++++
> tools/include/uapi/linux/bpf.h | 11 +++++++++++
> 3 files changed, 42 insertions(+)
>
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index b0383d371b9a..ba33d5718d6b 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -4648,6 +4648,16 @@ union bpf_attr {
> * **-EOPNOTSUP** if IMA is disabled or **-EINVAL** if
> * invalid arguments are passed.
> *
> + * long bpf_ima_file_hash(struct file *file, void *dst, u32 size)
> + * Description
> + * Returns a calculated IMA hash of the *file*.
> + * If the hash is larger than *size*, then only *size*
> + * bytes will be copied to *dst*
> + * Return
> + * The **hash_algo** is returned on success,
> + * **-EOPNOTSUP** if the hash calculation failed or **-EINVAL** if
> + * invalid arguments are passed.
> + *
> * struct socket *bpf_sock_from_file(struct file *file)
> * Description
> * If the given file represents a socket, returns the associated
> @@ -5182,6 +5192,7 @@ union bpf_attr {
> FN(bprm_opts_set), \
> FN(ktime_get_coarse_ns), \
> FN(ima_inode_hash), \
> + FN(ima_file_hash), \
Please put the above FN(ima_file_hash) to the end of the list.
Otherwise, we have a backward compatability issue.
> FN(sock_from_file), \
> FN(check_mtu), \
> FN(for_each_map_elem), \
> diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c
> index 9e4ecc990647..e8d27af5bbcc 100644
> --- a/kernel/bpf/bpf_lsm.c
> +++ b/kernel/bpf/bpf_lsm.c
[...]
^ permalink raw reply
* RE: [PATCH v2 6/6] selftests/bpf: Add test for bpf_lsm_kernel_read_file()
From: Roberto Sassu @ 2022-02-15 16:20 UTC (permalink / raw)
To: Shuah Khan, zohar@linux.ibm.com, shuah@kernel.org, ast@kernel.org,
daniel@iogearbox.net, andrii@kernel.org, kpsingh@kernel.org,
revest@chromium.org
Cc: linux-integrity@vger.kernel.org,
linux-security-module@vger.kernel.org,
linux-kselftest@vger.kernel.org, netdev@vger.kernel.org,
bpf@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <a06aaff2-2760-faff-db00-082543953bfe@linuxfoundation.org>
> From: Shuah Khan [mailto:skhan@linuxfoundation.org]
> Sent: Tuesday, February 15, 2022 5:11 PM
> On 2/15/22 5:40 AM, Roberto Sassu wrote:
> > Test the ability of bpf_lsm_kernel_read_file() to call the sleepable
> > functions bpf_ima_inode_hash() or bpf_ima_file_hash() to obtain a
> > measurement of a loaded IMA policy.
> >
> > Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> > ---
> > tools/testing/selftests/bpf/ima_setup.sh | 2 ++
> > .../selftests/bpf/prog_tests/test_ima.c | 3 +-
> > tools/testing/selftests/bpf/progs/ima.c | 28 ++++++++++++++++---
> > 3 files changed, 28 insertions(+), 5 deletions(-)
> >
> > diff --git a/tools/testing/selftests/bpf/ima_setup.sh
> b/tools/testing/selftests/bpf/ima_setup.sh
> > index 8e62581113a3..82530f19f85a 100755
> > --- a/tools/testing/selftests/bpf/ima_setup.sh
> > +++ b/tools/testing/selftests/bpf/ima_setup.sh
> > @@ -51,6 +51,7 @@ setup()
> >
> > ensure_mount_securityfs
> > echo "measure func=BPRM_CHECK fsuuid=${mount_uuid}" >
> ${IMA_POLICY_FILE}
> > + echo "measure func=BPRM_CHECK fsuuid=${mount_uuid}" >
> ${mount_dir}/policy_test
> > }
> >
> > cleanup() {
> > @@ -74,6 +75,7 @@ run()
> > local mount_dir="${tmp_dir}/mnt"
> > local copied_bin_path="${mount_dir}/$(basename ${TEST_BINARY})"
> >
> > + echo ${mount_dir}/policy_test > ${IMA_POLICY_FILE}
> > exec "${copied_bin_path}"
> > }
> >
> > diff --git a/tools/testing/selftests/bpf/prog_tests/test_ima.c
> b/tools/testing/selftests/bpf/prog_tests/test_ima.c
> > index 62bf0e830453..c4a62d7b70df 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/test_ima.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/test_ima.c
> > @@ -97,8 +97,9 @@ void test_test_ima(void)
> > /*
> > * 1 sample with use_ima_file_hash = false
> > * 2 samples with use_ima_file_hash = true (./ima_setup.sh, /bin/true)
> > + * 1 sample with use_ima_file_hash = true (IMA policy)
> > */
> > - ASSERT_EQ(err, 3, "num_samples_or_err");
> > + ASSERT_EQ(err, 4, "num_samples_or_err");
> > ASSERT_NEQ(ima_hash_from_bpf, 0, "ima_hash");
> >
> > close_clean:
> > diff --git a/tools/testing/selftests/bpf/progs/ima.c
> b/tools/testing/selftests/bpf/progs/ima.c
> > index 9bb63f96cfc0..9b4c03f30a1c 100644
> > --- a/tools/testing/selftests/bpf/progs/ima.c
> > +++ b/tools/testing/selftests/bpf/progs/ima.c
> > @@ -20,8 +20,7 @@ char _license[] SEC("license") = "GPL";
> >
> > bool use_ima_file_hash;
> >
> > -SEC("lsm.s/bprm_committed_creds")
> > -void BPF_PROG(ima, struct linux_binprm *bprm)
> > +static void ima_test_common(struct file *file)
> > {
> > u64 ima_hash = 0;
> > u64 *sample;
> > @@ -31,10 +30,10 @@ void BPF_PROG(ima, struct linux_binprm *bprm)
> > pid = bpf_get_current_pid_tgid() >> 32;
> > if (pid == monitored_pid) {
> > if (!use_ima_file_hash)
> > - ret = bpf_ima_inode_hash(bprm->file->f_inode,
> &ima_hash,
> > + ret = bpf_ima_inode_hash(file->f_inode, &ima_hash,
> > sizeof(ima_hash));
> > else
> > - ret = bpf_ima_file_hash(bprm->file, &ima_hash,
> > + ret = bpf_ima_file_hash(file, &ima_hash,
> > sizeof(ima_hash));
> > if (ret < 0 || ima_hash == 0)
>
> Is this considered an error? Does it make sense for this test to be
> void type and not return the error to its callers? One of the callers
> below seems to care for return values.
The user space side of the test (test_ima.c) seems to check the
number of samples obtained from the ring buffer. A failure here
would result in the sample not being sent to that component.
Another test, as you suggest, could be to ensure that the
kernel_read_file hook is able to deny operations. I would check
this in a separate test.
Thanks
Roberto
HUAWEI TECHNOLOGIES Duesseldorf GmbH, HRB 56063
Managing Director: Li Peng, Zhong Ronghua
> > return;
> > @@ -49,3 +48,24 @@ void BPF_PROG(ima, struct linux_binprm *bprm)
> >
> > return;
> > }
> > +
> > +SEC("lsm.s/bprm_committed_creds")
> > +void BPF_PROG(ima, struct linux_binprm *bprm)
> > +{
> > + ima_test_common(bprm->file);
> > +}
> > +
> > +SEC("lsm.s/kernel_read_file")
> > +int BPF_PROG(kernel_read_file, struct file *file, enum kernel_read_file_id id,
> > + bool contents)
> > +{
> > + if (!contents)
> > + return 0;
> > +
> > + if (id != READING_POLICY)
> > + return 0;
> > +
> > + ima_test_common(file);
>
> This one here.
>
> > +
> > + return 0;
> > +}
> >
>
> thanks,
> -- Shuah
^ permalink raw reply
* Re: [PATCH v2 6/6] selftests/bpf: Add test for bpf_lsm_kernel_read_file()
From: Shuah Khan @ 2022-02-15 16:11 UTC (permalink / raw)
To: Roberto Sassu, zohar, shuah, ast, daniel, andrii, kpsingh, revest
Cc: linux-integrity, linux-security-module, linux-kselftest, netdev,
bpf, linux-kernel, Shuah Khan
In-Reply-To: <20220215124042.186506-7-roberto.sassu@huawei.com>
On 2/15/22 5:40 AM, Roberto Sassu wrote:
> Test the ability of bpf_lsm_kernel_read_file() to call the sleepable
> functions bpf_ima_inode_hash() or bpf_ima_file_hash() to obtain a
> measurement of a loaded IMA policy.
>
> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> ---
> tools/testing/selftests/bpf/ima_setup.sh | 2 ++
> .../selftests/bpf/prog_tests/test_ima.c | 3 +-
> tools/testing/selftests/bpf/progs/ima.c | 28 ++++++++++++++++---
> 3 files changed, 28 insertions(+), 5 deletions(-)
>
> diff --git a/tools/testing/selftests/bpf/ima_setup.sh b/tools/testing/selftests/bpf/ima_setup.sh
> index 8e62581113a3..82530f19f85a 100755
> --- a/tools/testing/selftests/bpf/ima_setup.sh
> +++ b/tools/testing/selftests/bpf/ima_setup.sh
> @@ -51,6 +51,7 @@ setup()
>
> ensure_mount_securityfs
> echo "measure func=BPRM_CHECK fsuuid=${mount_uuid}" > ${IMA_POLICY_FILE}
> + echo "measure func=BPRM_CHECK fsuuid=${mount_uuid}" > ${mount_dir}/policy_test
> }
>
> cleanup() {
> @@ -74,6 +75,7 @@ run()
> local mount_dir="${tmp_dir}/mnt"
> local copied_bin_path="${mount_dir}/$(basename ${TEST_BINARY})"
>
> + echo ${mount_dir}/policy_test > ${IMA_POLICY_FILE}
> exec "${copied_bin_path}"
> }
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/test_ima.c b/tools/testing/selftests/bpf/prog_tests/test_ima.c
> index 62bf0e830453..c4a62d7b70df 100644
> --- a/tools/testing/selftests/bpf/prog_tests/test_ima.c
> +++ b/tools/testing/selftests/bpf/prog_tests/test_ima.c
> @@ -97,8 +97,9 @@ void test_test_ima(void)
> /*
> * 1 sample with use_ima_file_hash = false
> * 2 samples with use_ima_file_hash = true (./ima_setup.sh, /bin/true)
> + * 1 sample with use_ima_file_hash = true (IMA policy)
> */
> - ASSERT_EQ(err, 3, "num_samples_or_err");
> + ASSERT_EQ(err, 4, "num_samples_or_err");
> ASSERT_NEQ(ima_hash_from_bpf, 0, "ima_hash");
>
> close_clean:
> diff --git a/tools/testing/selftests/bpf/progs/ima.c b/tools/testing/selftests/bpf/progs/ima.c
> index 9bb63f96cfc0..9b4c03f30a1c 100644
> --- a/tools/testing/selftests/bpf/progs/ima.c
> +++ b/tools/testing/selftests/bpf/progs/ima.c
> @@ -20,8 +20,7 @@ char _license[] SEC("license") = "GPL";
>
> bool use_ima_file_hash;
>
> -SEC("lsm.s/bprm_committed_creds")
> -void BPF_PROG(ima, struct linux_binprm *bprm)
> +static void ima_test_common(struct file *file)
> {
> u64 ima_hash = 0;
> u64 *sample;
> @@ -31,10 +30,10 @@ void BPF_PROG(ima, struct linux_binprm *bprm)
> pid = bpf_get_current_pid_tgid() >> 32;
> if (pid == monitored_pid) {
> if (!use_ima_file_hash)
> - ret = bpf_ima_inode_hash(bprm->file->f_inode, &ima_hash,
> + ret = bpf_ima_inode_hash(file->f_inode, &ima_hash,
> sizeof(ima_hash));
> else
> - ret = bpf_ima_file_hash(bprm->file, &ima_hash,
> + ret = bpf_ima_file_hash(file, &ima_hash,
> sizeof(ima_hash));
> if (ret < 0 || ima_hash == 0)
Is this considered an error? Does it make sense for this test to be
void type and not return the error to its callers? One of the callers
below seems to care for return values.
> return;
> @@ -49,3 +48,24 @@ void BPF_PROG(ima, struct linux_binprm *bprm)
>
> return;
> }
> +
> +SEC("lsm.s/bprm_committed_creds")
> +void BPF_PROG(ima, struct linux_binprm *bprm)
> +{
> + ima_test_common(bprm->file);
> +}
> +
> +SEC("lsm.s/kernel_read_file")
> +int BPF_PROG(kernel_read_file, struct file *file, enum kernel_read_file_id id,
> + bool contents)
> +{
> + if (!contents)
> + return 0;
> +
> + if (id != READING_POLICY)
> + return 0;
> +
> + ima_test_common(file);
This one here.
> +
> + return 0;
> +}
>
thanks,
-- Shuah
^ permalink raw reply
* Re: [PATCH v2 4/6] selftests/bpf: Add test for bpf_ima_file_hash()
From: Shuah Khan @ 2022-02-15 16:00 UTC (permalink / raw)
To: Roberto Sassu, zohar, shuah, ast, daniel, andrii, kpsingh, revest
Cc: linux-integrity, linux-security-module, linux-kselftest, netdev,
bpf, linux-kernel, Shuah Khan
In-Reply-To: <20220215124042.186506-5-roberto.sassu@huawei.com>
On 2/15/22 5:40 AM, Roberto Sassu wrote:
> Modify the existing IMA test to call bpf_ima_file_hash() and update the
> expected result accordingly.
>
> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> ---
> .../selftests/bpf/prog_tests/test_ima.c | 29 ++++++++++++++++---
> tools/testing/selftests/bpf/progs/ima.c | 10 +++++--
> 2 files changed, 33 insertions(+), 6 deletions(-)
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/test_ima.c b/tools/testing/selftests/bpf/prog_tests/test_ima.c
> index 97d8a6f84f4a..62bf0e830453 100644
> --- a/tools/testing/selftests/bpf/prog_tests/test_ima.c
> +++ b/tools/testing/selftests/bpf/prog_tests/test_ima.c
> @@ -13,9 +13,10 @@
>
> #include "ima.skel.h"
>
> -static int run_measured_process(const char *measured_dir, u32 *monitored_pid)
> +static int run_measured_process(const char *measured_dir, u32 *monitored_pid,
> + bool *use_ima_file_hash)
> {
> - int child_pid, child_status;
> + int err, child_pid, child_status;
>
> child_pid = fork();
> if (child_pid == 0) {
> @@ -24,6 +25,21 @@ static int run_measured_process(const char *measured_dir, u32 *monitored_pid)
> NULL);
> exit(errno);
>
> + } else if (child_pid > 0) {
> + waitpid(child_pid, &child_status, 0);
> + err = WEXITSTATUS(child_status);
> + if (err)
> + return err;
> + }
> +
> + child_pid = fork();
> + if (child_pid == 0) {
> + *monitored_pid = getpid();
> + *use_ima_file_hash = true;
> + execlp("./ima_setup.sh", "./ima_setup.sh", "run", measured_dir,
> + NULL);
> + exit(errno);
> +
> } else if (child_pid > 0) {
> waitpid(child_pid, &child_status, 0);
> return WEXITSTATUS(child_status);
> @@ -72,12 +88,17 @@ void test_test_ima(void)
> if (CHECK(err, "failed to run command", "%s, errno = %d\n", cmd, errno))
> goto close_clean;
>
> - err = run_measured_process(measured_dir, &skel->bss->monitored_pid);
> + err = run_measured_process(measured_dir, &skel->bss->monitored_pid,
> + &skel->bss->use_ima_file_hash);
> if (CHECK(err, "run_measured_process", "err = %d\n", err))
> goto close_clean;
>
> err = ring_buffer__consume(ringbuf);
> - ASSERT_EQ(err, 1, "num_samples_or_err");
> + /*
> + * 1 sample with use_ima_file_hash = false
> + * 2 samples with use_ima_file_hash = true (./ima_setup.sh, /bin/true)
> + */
> + ASSERT_EQ(err, 3, "num_samples_or_err");
> ASSERT_NEQ(ima_hash_from_bpf, 0, "ima_hash");
>
> close_clean:
> diff --git a/tools/testing/selftests/bpf/progs/ima.c b/tools/testing/selftests/bpf/progs/ima.c
> index 96060ff4ffc6..9bb63f96cfc0 100644
> --- a/tools/testing/selftests/bpf/progs/ima.c
> +++ b/tools/testing/selftests/bpf/progs/ima.c
> @@ -18,6 +18,8 @@ struct {
>
> char _license[] SEC("license") = "GPL";
>
> +bool use_ima_file_hash;
> +
This can be statis.
> SEC("lsm.s/bprm_committed_creds")
> void BPF_PROG(ima, struct linux_binprm *bprm)
> {
> @@ -28,8 +30,12 @@ void BPF_PROG(ima, struct linux_binprm *bprm)
>
> pid = bpf_get_current_pid_tgid() >> 32;
> if (pid == monitored_pid) {
I also noticed monitored_pid is defined in several bpf. Potentially
could be made static. This isn't introduced in this patch though.
> - ret = bpf_ima_inode_hash(bprm->file->f_inode, &ima_hash,
> - sizeof(ima_hash));
> + if (!use_ima_file_hash)
> + ret = bpf_ima_inode_hash(bprm->file->f_inode, &ima_hash,
> + sizeof(ima_hash));
> + else
> + ret = bpf_ima_file_hash(bprm->file, &ima_hash,
> + sizeof(ima_hash));
> if (ret < 0 || ima_hash == 0)
> return;
>
>
thanks,
-- Shuah
^ permalink raw reply
* RE: [PATCH v2 1/6] ima: Fix documentation-related warnings in ima_main.c
From: Roberto Sassu @ 2022-02-15 15:58 UTC (permalink / raw)
To: Shuah Khan, zohar@linux.ibm.com, shuah@kernel.org, ast@kernel.org,
daniel@iogearbox.net, andrii@kernel.org, kpsingh@kernel.org,
revest@chromium.org
Cc: linux-integrity@vger.kernel.org,
linux-security-module@vger.kernel.org,
linux-kselftest@vger.kernel.org, netdev@vger.kernel.org,
bpf@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <759a70de-a06b-592c-de4a-f7c74fbe4619@linuxfoundation.org>
> From: Shuah Khan [mailto:skhan@linuxfoundation.org]
> Sent: Tuesday, February 15, 2022 4:46 PM
> On 2/15/22 5:40 AM, Roberto Sassu wrote:
> > Fix some warnings in ima_main.c, displayed with W=n make argument.
> >
>
> Thank you for fixing these. Doc builds are full of them and few less
> is welcome.
>
> Adding the warns or summary of them to change log will be good.
Hi Shuah
ok, I will add a brief description of what I fixed in the next version
of the patch set.
Thanks
Roberto
HUAWEI TECHNOLOGIES Duesseldorf GmbH, HRB 56063
Managing Director: Li Peng, Zhong Ronghua
> > Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> > ---
> > security/integrity/ima/ima_main.c | 11 ++++++-----
> > 1 file changed, 6 insertions(+), 5 deletions(-)
> >
> > diff --git a/security/integrity/ima/ima_main.c
> b/security/integrity/ima/ima_main.c
> > index 8c6e4514d494..946ba8a12eab 100644
> > --- a/security/integrity/ima/ima_main.c
> > +++ b/security/integrity/ima/ima_main.c
> > @@ -418,6 +418,7 @@ int ima_file_mmap(struct file *file, unsigned long prot)
> >
> > /**
> > * ima_file_mprotect - based on policy, limit mprotect change
> > + * @vma: vm_area_struct protection is set to
> > * @prot: contains the protection that will be applied by the kernel.
> > *
>
>
> Reviewed-by: Shuah Khan <skhan@linuxfoundation.org>
>
> thanks,
> -- Shuah
^ permalink raw reply
* Re: [PATCH v2 1/6] ima: Fix documentation-related warnings in ima_main.c
From: Shuah Khan @ 2022-02-15 15:46 UTC (permalink / raw)
To: Roberto Sassu, zohar, shuah, ast, daniel, andrii, kpsingh, revest
Cc: linux-integrity, linux-security-module, linux-kselftest, netdev,
bpf, linux-kernel, Shuah Khan
In-Reply-To: <20220215124042.186506-2-roberto.sassu@huawei.com>
On 2/15/22 5:40 AM, Roberto Sassu wrote:
> Fix some warnings in ima_main.c, displayed with W=n make argument.
>
Thank you for fixing these. Doc builds are full of them and few less
is welcome.
Adding the warns or summary of them to change log will be good.
> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> ---
> security/integrity/ima/ima_main.c | 11 ++++++-----
> 1 file changed, 6 insertions(+), 5 deletions(-)
>
> diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> index 8c6e4514d494..946ba8a12eab 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -418,6 +418,7 @@ int ima_file_mmap(struct file *file, unsigned long prot)
>
> /**
> * ima_file_mprotect - based on policy, limit mprotect change
> + * @vma: vm_area_struct protection is set to
> * @prot: contains the protection that will be applied by the kernel.
> *
Reviewed-by: Shuah Khan <skhan@linuxfoundation.org>
thanks,
-- Shuah
^ permalink raw reply
* [PATCH v5] KEYS: encrypted: Instantiate key with user-provided decrypted data
From: Yael Tzur @ 2022-02-15 14:19 UTC (permalink / raw)
To: linux-integrity
Cc: jejb, jarkko, zohar, corbet, dhowells, jmorris, serge, keyrings,
linux-doc, linux-kernel, linux-security-module, Yael Tzur
For availability and performance reasons master keys often need to be
released outside of a Key Management Service (KMS) to clients. It
would be beneficial to provide a mechanism where the
wrapping/unwrapping of data encryption keys (DEKs) is not dependent
on a remote call at runtime yet security is not (or only minimally)
compromised. Master keys could be securely stored in the Kernel and
be used to wrap/unwrap keys from Userspace.
The encrypted.c class supports instantiation of encrypted keys with
either an already-encrypted key material, or by generating new key
material based on random numbers. This patch defines a new datablob
format: [<format>] <master-key name> <decrypted data length>
<decrypted data> that allows to inject and encrypt user-provided
decrypted data. The decrypted data must be hex-ascii encoded.
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
Signed-off-by: Yael Tzur <yaelt@google.com>
---
Notes:
v -> v2: fixed compilation error.
v2 -> v3: modified documentation.
v3 -> v4: modified commit message.
v4 -> v5: added config option to enable feature, and modified input validation.
.../security/keys/trusted-encrypted.rst | 25 +++++--
security/keys/Kconfig | 19 +++--
security/keys/encrypted-keys/encrypted.c | 72 ++++++++++++++-----
3 files changed, 87 insertions(+), 29 deletions(-)
diff --git a/Documentation/security/keys/trusted-encrypted.rst b/Documentation/security/keys/trusted-encrypted.rst
index 80d5a5af62a1..f614dad7de12 100644
--- a/Documentation/security/keys/trusted-encrypted.rst
+++ b/Documentation/security/keys/trusted-encrypted.rst
@@ -107,12 +107,13 @@ Encrypted Keys
--------------
Encrypted keys do not depend on a trust source, and are faster, as they use AES
-for encryption/decryption. New keys are created from kernel-generated random
-numbers, and are encrypted/decrypted using a specified ‘master’ key. The
-‘master’ key can either be a trusted-key or user-key type. The main disadvantage
-of encrypted keys is that if they are not rooted in a trusted key, they are only
-as secure as the user key encrypting them. The master user key should therefore
-be loaded in as secure a way as possible, preferably early in boot.
+for encryption/decryption. New keys are created either from kernel-generated
+random numbers or user-provided decrypted data, and are encrypted/decrypted
+using a specified ‘master’ key. The ‘master’ key can either be a trusted-key or
+user-key type. The main disadvantage of encrypted keys is that if they are not
+rooted in a trusted key, they are only as secure as the user key encrypting
+them. The master user key should therefore be loaded in as secure a way as
+possible, preferably early in boot.
Usage
@@ -199,6 +200,8 @@ Usage::
keyctl add encrypted name "new [format] key-type:master-key-name keylen"
ring
+ keyctl add encrypted name "new [format] key-type:master-key-name keylen
+ decrypted-data" ring
keyctl add encrypted name "load hex_blob" ring
keyctl update keyid "update key-type:master-key-name"
@@ -303,6 +306,16 @@ Load an encrypted key "evm" from saved blob::
82dbbc55be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e0
24717c64 5972dcb82ab2dde83376d82b2e3c09ffc
+Instantiate an encrypted key "evm" using user-provided decrypted data::
+
+ $ keyctl add encrypted evm "new default user:kmk 32 `cat evm_decrypted_data.blob`" @u
+ 794890253
+
+ $ keyctl print 794890253
+ default user:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b382d
+ bbc55be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e0247
+ 17c64 5972dcb82ab2dde83376d82b2e3c09ffc
+
Other uses for trusted and encrypted keys, such as for disk and file encryption
are anticipated. In particular the new format 'ecryptfs' has been defined
in order to use encrypted keys to mount an eCryptfs filesystem. More details
diff --git a/security/keys/Kconfig b/security/keys/Kconfig
index 969122c7b92f..0e30b361e1c1 100644
--- a/security/keys/Kconfig
+++ b/security/keys/Kconfig
@@ -98,10 +98,21 @@ config ENCRYPTED_KEYS
select CRYPTO_RNG
help
This option provides support for create/encrypting/decrypting keys
- in the kernel. Encrypted keys are kernel generated random numbers,
- which are encrypted/decrypted with a 'master' symmetric key. The
- 'master' key can be either a trusted-key or user-key type.
- Userspace only ever sees/stores encrypted blobs.
+ in the kernel. Encrypted keys are instantiated using kernel
+ generated random numbers or provided decrypted data, and are
+ encrypted/decrypted with a 'master' symmetric key. The 'master'
+ key can be either a trusted-key or user-key type. Only encrypted
+ blobs are ever output to Userspace.
+
+ If you are unsure as to whether this is required, answer N.
+
+config USER_DECRYPTED_DATA
+ bool "Allow encrypted keys with user decrypted data"
+ depends on ENCRYPTED_KEYS
+ help
+ This option provides support for instantiating encrypted keys using
+ user-provided decrypted data. The decrypted data must be hex-ascii
+ encoded.
If you are unsure as to whether this is required, answer N.
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c
index 87432b35d771..ebfb8129fb92 100644
--- a/security/keys/encrypted-keys/encrypted.c
+++ b/security/keys/encrypted-keys/encrypted.c
@@ -78,6 +78,11 @@ static const match_table_t key_tokens = {
{Opt_err, NULL}
};
+static bool user_decrypted_data = IS_ENABLED(CONFIG_USER_DECRYPTED_DATA);
+module_param(user_decrypted_data, bool, 0);
+MODULE_PARM_DESC(user_decrypted_data,
+ "Allow instantiation of encrypted keys using provided decrypted data");
+
static int aes_get_sizes(void)
{
struct crypto_skcipher *tfm;
@@ -158,7 +163,7 @@ static int valid_master_desc(const char *new_desc, const char *orig_desc)
* datablob_parse - parse the keyctl data
*
* datablob format:
- * new [<format>] <master-key name> <decrypted data length>
+ * new [<format>] <master-key name> <decrypted data length> [<decrypted data>]
* load [<format>] <master-key name> <decrypted data length>
* <encrypted iv + data>
* update <new-master-key name>
@@ -170,7 +175,7 @@ static int valid_master_desc(const char *new_desc, const char *orig_desc)
*/
static int datablob_parse(char *datablob, const char **format,
char **master_desc, char **decrypted_datalen,
- char **hex_encoded_iv)
+ char **hex_encoded_iv, char **decrypted_data)
{
substring_t args[MAX_OPT_ARGS];
int ret = -EINVAL;
@@ -231,6 +236,7 @@ static int datablob_parse(char *datablob, const char **format,
"when called from .update method\n", keyword);
break;
}
+ *decrypted_data = strsep(&datablob, " \t");
ret = 0;
break;
case Opt_load:
@@ -595,7 +601,8 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload,
static struct encrypted_key_payload *encrypted_key_alloc(struct key *key,
const char *format,
const char *master_desc,
- const char *datalen)
+ const char *datalen,
+ const char *decrypted_data)
{
struct encrypted_key_payload *epayload = NULL;
unsigned short datablob_len;
@@ -604,6 +611,7 @@ static struct encrypted_key_payload *encrypted_key_alloc(struct key *key,
unsigned int encrypted_datalen;
unsigned int format_len;
long dlen;
+ int i;
int ret;
ret = kstrtol(datalen, 10, &dlen);
@@ -613,6 +620,24 @@ static struct encrypted_key_payload *encrypted_key_alloc(struct key *key,
format_len = (!format) ? strlen(key_format_default) : strlen(format);
decrypted_datalen = dlen;
payload_datalen = decrypted_datalen;
+
+ if (decrypted_data) {
+ if (!user_decrypted_data) {
+ pr_err("encrypted key: instantiation of keys using provided decrypted data is disabled since CONFIG_USER_DECRYPTED_DATA is set to false\n");
+ return ERR_PTR(-EINVAL);
+ }
+ if (strlen(decrypted_data) != decrypted_datalen) {
+ pr_err("encrypted key: decrypted data provided does not match decrypted data length provided\n");
+ return ERR_PTR(-EINVAL);
+ }
+ for (i = 0; i < strlen(decrypted_data); i++) {
+ if (!isxdigit(decrypted_data[i])) {
+ pr_err("encrypted key: decrypted data provided must contain only hexadecimal characters\n");
+ return ERR_PTR(-EINVAL);
+ }
+ }
+ }
+
if (format) {
if (!strcmp(format, key_format_ecryptfs)) {
if (dlen != ECRYPTFS_MAX_KEY_BYTES) {
@@ -740,13 +766,14 @@ static void __ekey_init(struct encrypted_key_payload *epayload,
/*
* encrypted_init - initialize an encrypted key
*
- * For a new key, use a random number for both the iv and data
- * itself. For an old key, decrypt the hex encoded data.
+ * For a new key, use either a random number or user-provided decrypted data in
+ * case it is provided. A random number is used for the iv in both cases. For
+ * an old key, decrypt the hex encoded data.
*/
static int encrypted_init(struct encrypted_key_payload *epayload,
const char *key_desc, const char *format,
const char *master_desc, const char *datalen,
- const char *hex_encoded_iv)
+ const char *hex_encoded_iv, const char *decrypted_data)
{
int ret = 0;
@@ -760,21 +787,26 @@ static int encrypted_init(struct encrypted_key_payload *epayload,
}
__ekey_init(epayload, format, master_desc, datalen);
- if (!hex_encoded_iv) {
- get_random_bytes(epayload->iv, ivsize);
-
- get_random_bytes(epayload->decrypted_data,
- epayload->decrypted_datalen);
- } else
+ if (hex_encoded_iv) {
ret = encrypted_key_decrypt(epayload, format, hex_encoded_iv);
+ } else if (decrypted_data) {
+ get_random_bytes(epayload->iv, ivsize);
+ memcpy(epayload->decrypted_data, decrypted_data,
+ epayload->decrypted_datalen);
+ } else {
+ get_random_bytes(epayload->iv, ivsize);
+ get_random_bytes(epayload->decrypted_data, epayload->decrypted_datalen);
+ }
return ret;
}
/*
* encrypted_instantiate - instantiate an encrypted key
*
- * Decrypt an existing encrypted datablob or create a new encrypted key
- * based on a kernel random number.
+ * Instantiates the key:
+ * - by decrypting an existing encrypted datablob, or
+ * - by creating a new encrypted key based on a kernel random number, or
+ * - using provided decrypted data.
*
* On success, return 0. Otherwise return errno.
*/
@@ -787,6 +819,7 @@ static int encrypted_instantiate(struct key *key,
char *master_desc = NULL;
char *decrypted_datalen = NULL;
char *hex_encoded_iv = NULL;
+ char *decrypted_data = NULL;
size_t datalen = prep->datalen;
int ret;
@@ -799,18 +832,18 @@ static int encrypted_instantiate(struct key *key,
datablob[datalen] = 0;
memcpy(datablob, prep->data, datalen);
ret = datablob_parse(datablob, &format, &master_desc,
- &decrypted_datalen, &hex_encoded_iv);
+ &decrypted_datalen, &hex_encoded_iv, &decrypted_data);
if (ret < 0)
goto out;
epayload = encrypted_key_alloc(key, format, master_desc,
- decrypted_datalen);
+ decrypted_datalen, decrypted_data);
if (IS_ERR(epayload)) {
ret = PTR_ERR(epayload);
goto out;
}
ret = encrypted_init(epayload, key->description, format, master_desc,
- decrypted_datalen, hex_encoded_iv);
+ decrypted_datalen, hex_encoded_iv, decrypted_data);
if (ret < 0) {
kfree_sensitive(epayload);
goto out;
@@ -860,7 +893,7 @@ static int encrypted_update(struct key *key, struct key_preparsed_payload *prep)
buf[datalen] = 0;
memcpy(buf, prep->data, datalen);
- ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL);
+ ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL, NULL);
if (ret < 0)
goto out;
@@ -869,7 +902,7 @@ static int encrypted_update(struct key *key, struct key_preparsed_payload *prep)
goto out;
new_epayload = encrypted_key_alloc(key, epayload->format,
- new_master_desc, epayload->datalen);
+ new_master_desc, epayload->datalen, NULL);
if (IS_ERR(new_epayload)) {
ret = PTR_ERR(new_epayload);
goto out;
--
2.35.1.265.g69c8d7142f-goog
^ permalink raw reply related
* [PATCH v2 6/6] selftests/bpf: Add test for bpf_lsm_kernel_read_file()
From: Roberto Sassu @ 2022-02-15 12:40 UTC (permalink / raw)
To: zohar, shuah, ast, daniel, andrii, kpsingh, revest
Cc: linux-integrity, linux-security-module, linux-kselftest, netdev,
bpf, linux-kernel, Roberto Sassu
In-Reply-To: <20220215124042.186506-1-roberto.sassu@huawei.com>
Test the ability of bpf_lsm_kernel_read_file() to call the sleepable
functions bpf_ima_inode_hash() or bpf_ima_file_hash() to obtain a
measurement of a loaded IMA policy.
Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
---
tools/testing/selftests/bpf/ima_setup.sh | 2 ++
.../selftests/bpf/prog_tests/test_ima.c | 3 +-
tools/testing/selftests/bpf/progs/ima.c | 28 ++++++++++++++++---
3 files changed, 28 insertions(+), 5 deletions(-)
diff --git a/tools/testing/selftests/bpf/ima_setup.sh b/tools/testing/selftests/bpf/ima_setup.sh
index 8e62581113a3..82530f19f85a 100755
--- a/tools/testing/selftests/bpf/ima_setup.sh
+++ b/tools/testing/selftests/bpf/ima_setup.sh
@@ -51,6 +51,7 @@ setup()
ensure_mount_securityfs
echo "measure func=BPRM_CHECK fsuuid=${mount_uuid}" > ${IMA_POLICY_FILE}
+ echo "measure func=BPRM_CHECK fsuuid=${mount_uuid}" > ${mount_dir}/policy_test
}
cleanup() {
@@ -74,6 +75,7 @@ run()
local mount_dir="${tmp_dir}/mnt"
local copied_bin_path="${mount_dir}/$(basename ${TEST_BINARY})"
+ echo ${mount_dir}/policy_test > ${IMA_POLICY_FILE}
exec "${copied_bin_path}"
}
diff --git a/tools/testing/selftests/bpf/prog_tests/test_ima.c b/tools/testing/selftests/bpf/prog_tests/test_ima.c
index 62bf0e830453..c4a62d7b70df 100644
--- a/tools/testing/selftests/bpf/prog_tests/test_ima.c
+++ b/tools/testing/selftests/bpf/prog_tests/test_ima.c
@@ -97,8 +97,9 @@ void test_test_ima(void)
/*
* 1 sample with use_ima_file_hash = false
* 2 samples with use_ima_file_hash = true (./ima_setup.sh, /bin/true)
+ * 1 sample with use_ima_file_hash = true (IMA policy)
*/
- ASSERT_EQ(err, 3, "num_samples_or_err");
+ ASSERT_EQ(err, 4, "num_samples_or_err");
ASSERT_NEQ(ima_hash_from_bpf, 0, "ima_hash");
close_clean:
diff --git a/tools/testing/selftests/bpf/progs/ima.c b/tools/testing/selftests/bpf/progs/ima.c
index 9bb63f96cfc0..9b4c03f30a1c 100644
--- a/tools/testing/selftests/bpf/progs/ima.c
+++ b/tools/testing/selftests/bpf/progs/ima.c
@@ -20,8 +20,7 @@ char _license[] SEC("license") = "GPL";
bool use_ima_file_hash;
-SEC("lsm.s/bprm_committed_creds")
-void BPF_PROG(ima, struct linux_binprm *bprm)
+static void ima_test_common(struct file *file)
{
u64 ima_hash = 0;
u64 *sample;
@@ -31,10 +30,10 @@ void BPF_PROG(ima, struct linux_binprm *bprm)
pid = bpf_get_current_pid_tgid() >> 32;
if (pid == monitored_pid) {
if (!use_ima_file_hash)
- ret = bpf_ima_inode_hash(bprm->file->f_inode, &ima_hash,
+ ret = bpf_ima_inode_hash(file->f_inode, &ima_hash,
sizeof(ima_hash));
else
- ret = bpf_ima_file_hash(bprm->file, &ima_hash,
+ ret = bpf_ima_file_hash(file, &ima_hash,
sizeof(ima_hash));
if (ret < 0 || ima_hash == 0)
return;
@@ -49,3 +48,24 @@ void BPF_PROG(ima, struct linux_binprm *bprm)
return;
}
+
+SEC("lsm.s/bprm_committed_creds")
+void BPF_PROG(ima, struct linux_binprm *bprm)
+{
+ ima_test_common(bprm->file);
+}
+
+SEC("lsm.s/kernel_read_file")
+int BPF_PROG(kernel_read_file, struct file *file, enum kernel_read_file_id id,
+ bool contents)
+{
+ if (!contents)
+ return 0;
+
+ if (id != READING_POLICY)
+ return 0;
+
+ ima_test_common(file);
+
+ return 0;
+}
--
2.32.0
^ permalink raw reply related
* [PATCH v2 5/6] bpf-lsm: Make bpf_lsm_kernel_read_file() as sleepable
From: Roberto Sassu @ 2022-02-15 12:40 UTC (permalink / raw)
To: zohar, shuah, ast, daniel, andrii, kpsingh, revest
Cc: linux-integrity, linux-security-module, linux-kselftest, netdev,
bpf, linux-kernel, Roberto Sassu
In-Reply-To: <20220215124042.186506-1-roberto.sassu@huawei.com>
Make bpf_lsm_kernel_read_file() as sleepable, so that bpf_ima_inode_hash()
or bpf_ima_file_hash() can be called inside the implementation of this
hook.
Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
---
kernel/bpf/bpf_lsm.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c
index e8d27af5bbcc..064eccba641d 100644
--- a/kernel/bpf/bpf_lsm.c
+++ b/kernel/bpf/bpf_lsm.c
@@ -187,6 +187,7 @@ BTF_ID(func, bpf_lsm_inode_setxattr)
BTF_ID(func, bpf_lsm_inode_symlink)
BTF_ID(func, bpf_lsm_inode_unlink)
BTF_ID(func, bpf_lsm_kernel_module_request)
+BTF_ID(func, bpf_lsm_kernel_read_file)
BTF_ID(func, bpf_lsm_kernfs_init_security)
#ifdef CONFIG_KEYS
--
2.32.0
^ permalink raw reply related
* [PATCH v2 4/6] selftests/bpf: Add test for bpf_ima_file_hash()
From: Roberto Sassu @ 2022-02-15 12:40 UTC (permalink / raw)
To: zohar, shuah, ast, daniel, andrii, kpsingh, revest
Cc: linux-integrity, linux-security-module, linux-kselftest, netdev,
bpf, linux-kernel, Roberto Sassu
In-Reply-To: <20220215124042.186506-1-roberto.sassu@huawei.com>
Modify the existing IMA test to call bpf_ima_file_hash() and update the
expected result accordingly.
Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
---
.../selftests/bpf/prog_tests/test_ima.c | 29 ++++++++++++++++---
tools/testing/selftests/bpf/progs/ima.c | 10 +++++--
2 files changed, 33 insertions(+), 6 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/test_ima.c b/tools/testing/selftests/bpf/prog_tests/test_ima.c
index 97d8a6f84f4a..62bf0e830453 100644
--- a/tools/testing/selftests/bpf/prog_tests/test_ima.c
+++ b/tools/testing/selftests/bpf/prog_tests/test_ima.c
@@ -13,9 +13,10 @@
#include "ima.skel.h"
-static int run_measured_process(const char *measured_dir, u32 *monitored_pid)
+static int run_measured_process(const char *measured_dir, u32 *monitored_pid,
+ bool *use_ima_file_hash)
{
- int child_pid, child_status;
+ int err, child_pid, child_status;
child_pid = fork();
if (child_pid == 0) {
@@ -24,6 +25,21 @@ static int run_measured_process(const char *measured_dir, u32 *monitored_pid)
NULL);
exit(errno);
+ } else if (child_pid > 0) {
+ waitpid(child_pid, &child_status, 0);
+ err = WEXITSTATUS(child_status);
+ if (err)
+ return err;
+ }
+
+ child_pid = fork();
+ if (child_pid == 0) {
+ *monitored_pid = getpid();
+ *use_ima_file_hash = true;
+ execlp("./ima_setup.sh", "./ima_setup.sh", "run", measured_dir,
+ NULL);
+ exit(errno);
+
} else if (child_pid > 0) {
waitpid(child_pid, &child_status, 0);
return WEXITSTATUS(child_status);
@@ -72,12 +88,17 @@ void test_test_ima(void)
if (CHECK(err, "failed to run command", "%s, errno = %d\n", cmd, errno))
goto close_clean;
- err = run_measured_process(measured_dir, &skel->bss->monitored_pid);
+ err = run_measured_process(measured_dir, &skel->bss->monitored_pid,
+ &skel->bss->use_ima_file_hash);
if (CHECK(err, "run_measured_process", "err = %d\n", err))
goto close_clean;
err = ring_buffer__consume(ringbuf);
- ASSERT_EQ(err, 1, "num_samples_or_err");
+ /*
+ * 1 sample with use_ima_file_hash = false
+ * 2 samples with use_ima_file_hash = true (./ima_setup.sh, /bin/true)
+ */
+ ASSERT_EQ(err, 3, "num_samples_or_err");
ASSERT_NEQ(ima_hash_from_bpf, 0, "ima_hash");
close_clean:
diff --git a/tools/testing/selftests/bpf/progs/ima.c b/tools/testing/selftests/bpf/progs/ima.c
index 96060ff4ffc6..9bb63f96cfc0 100644
--- a/tools/testing/selftests/bpf/progs/ima.c
+++ b/tools/testing/selftests/bpf/progs/ima.c
@@ -18,6 +18,8 @@ struct {
char _license[] SEC("license") = "GPL";
+bool use_ima_file_hash;
+
SEC("lsm.s/bprm_committed_creds")
void BPF_PROG(ima, struct linux_binprm *bprm)
{
@@ -28,8 +30,12 @@ void BPF_PROG(ima, struct linux_binprm *bprm)
pid = bpf_get_current_pid_tgid() >> 32;
if (pid == monitored_pid) {
- ret = bpf_ima_inode_hash(bprm->file->f_inode, &ima_hash,
- sizeof(ima_hash));
+ if (!use_ima_file_hash)
+ ret = bpf_ima_inode_hash(bprm->file->f_inode, &ima_hash,
+ sizeof(ima_hash));
+ else
+ ret = bpf_ima_file_hash(bprm->file, &ima_hash,
+ sizeof(ima_hash));
if (ret < 0 || ima_hash == 0)
return;
--
2.32.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox