[opensuse-kernel] [RFC PATCH 00/18 v2] Signature verification of hibernate snapshot
Hi experts, This patchset is the implementation for signature verification of hibernate snapshot image. The origin idea is from Jiri Kosina: Let EFI bootloader generate key-pair in UEFI secure boot environment, then pass it to kernel for sign/verify S4 image. Due to there have potential threat from the S4 image hacked, it may cause SUSE lost the trust in UEFI secure boot. The hacker attack the S4 snapshot image in swap partition through whatever exploit from another trusted OS, an the exploit may don't need physical access machine. So, this patchset give the ability to kernel for parsing the RSA key-pair from EFI bootloader, then using the private key to generate the signature of S4 snapshot image. Kernel put the signature to snapshot header, then verify the signature when kernel try to recover snapshot image to memory. ============== How To Enable ============== Set enable the CONFIG_SNAPSHOT_VERIFICATION kernel config. And you can also choice which hash algorithm should snapshot be signed with. Then rebuild kernel. Please note this function need UEFI bootloader generate key-pair in UEFI secure boot environment, e.g. shim. current shim implementation by Gary Lin: https://build.opensuse.org/package/show/home:gary_lin:UEFI/shim Please use the shim from the above URL if you want to try. And, Please remember add this shim to db in UEFI because it didn't sign by SUSE or Microsoft key. ========= Behavior ========= The RSA key-pair are generated by EFI bootloader(e.g. shim) in UEFI secure boot environment, so currently this function binding with EFI secure boot enabled. The kernel behavior is: + UEFI Secure Boot ON, Kernel found key-pair from shim: Kernel will do the S4 signature check. + UEFI Secure Boot ON, Kernel didn't find key-pair from shim: Kernel will lock down S4 function. + UEFI Secure Boot OFF Kernel will disable S4 signature check, and ignore any keys from EFI bootloader. On EFI bootloader side, the behavior as following: + First, kernel will check the following 2 EFI variable: S4SignKey-fe141863-c070-478e-b8a3-878a5dc9ef21 [Runtime][Non-Volatile] S4WakeKey-fe141863-c070-478e-b8a3-878a5dc9ef21 [Runtime][Volatile] S4SignKey and S4WakeKey is a RSA key-pair: - S4SignKey is a private key that's used to generate signature of S4 snapshot. The blob format of S4SignKey is PKCS#8 format, it should packaged a RSA private key that's followed PKCS#1. - S4WakeKey is a public key that's used to verify signature of S4 snapshot. The blob format of S4WakeKey is X.509 format, it should packaged a RSA public key that's followed PKCS#1. + EFI bootloader must generate RSA key-pair when system boot: - Bootloader store the public key to EFI boottime variable by itself - Bootloader put The private key to S4SignKey EFI variable for forward to kernel. + Kernel will load the S4SignKey blob to RAM when booting and delete it immediately. This private key will sign snapshot when S4. + When machine resume from hibernate: - EFI bootloader should copy the public key from boottime variable to S4WakeKey EFI variable. - Bootloader need generated a new key-pair for next round S4 usage. It should put new privat ekey to S4SignKey variable. ============== Implementation ============== Whole implementation including 3 part: shim, asymmetric keys and hibernate: + shim: Currently solution implemented by Gary Lin: https://build.opensuse.org/package/show/home:gary_lin:UEFI/shim Please use the shim from the above URL if you want to try. And, Please remember add this shim to db because it didn't sign by SUSE or Microsoft key. + Asymmetric keys: This patchset implemented PKCS#8 and RSA private key parser, it also implement the signature verification operation of RSASSA-PKCS1-v_5 in PKCS#1 spec. [RFC3447 sec 8.2.2] Set CONFIG_PKCS8_PRIVATE_KEY_INFO_PARSER=y will give kernel the abilities to parsing private key and verify signature. + Hibernate: Set CONFIG_SNAPSHOT_VERIFICATION=y will give enable the function of snapshot signature generation and verification. We reserved 512 byes size in snapshot header for store the signature that's generated from the digest with SHA256 algorithms. For adapt S4 signature check to secure boot, I have porting 3 patches from Fedora kernel to openSUSE, authors are Josh Boyer and Matthew Garrett. I also add Cc. to them. Please help review this RFC patchset! Appreciate for any comments! Josh Boyer (1): Secure boot: Add a dummy kernel parameter that will switch on Secure Boot mode Lee, Chun-Yi (15): asymmetric keys: add interface and skeleton for implement signature generation asymmetric keys: implement EMSA_PKCS1-v1_5-ENCODE in rsa asymmetric keys: separate the length checking of octet string from RSA_I2OSP asymmetric keys: implement OS2IP in rsa asymmetric keys: implement RSASP1 asymmetric keys: support parsing PKCS #8 private key information asymmetric keys: explicitly add the leading zero byte to encoded message Hibernate: introduced RSA key-pair to verify signature of snapshot Hibernate: generate and verify signature of snapshot Hibernate: Avoid S4 sign key data included in snapshot image Hibernate: fix the race condition of remove S4 sign key Hibernate: applied SNAPSHOT_VERIFICATION config to switch signature check Hibernate: adapt to UEFI secure boot with signature check Hibernate: show the verification time for monitor performance Hibernate: introduced SNAPSHOT_SIG_HASH config for select hash algorithm Matthew Garrett (2): Secure boot: Add new capability efi: Enable secure boot lockdown automatically when enabled in firmware Documentation/kernel-parameters.txt | 7 + Documentation/x86/zero-page.txt | 2 + arch/x86/boot/compressed/eboot.c | 32 +++ arch/x86/include/asm/bootparam_utils.h | 8 +- arch/x86/include/uapi/asm/bootparam.h | 3 +- arch/x86/kernel/setup.c | 7 + crypto/asymmetric_keys/Kconfig | 11 + crypto/asymmetric_keys/Makefile | 16 ++ crypto/asymmetric_keys/pkcs8.asn1 | 19 ++ crypto/asymmetric_keys/pkcs8_info_parser.c | 152 ++++++++++++++ crypto/asymmetric_keys/pkcs8_parser.h | 23 ++ crypto/asymmetric_keys/pkcs8_private_key.c | 148 ++++++++++++++ crypto/asymmetric_keys/pkcs8_rsakey.asn1 | 29 +++ crypto/asymmetric_keys/private_key.h | 29 +++ crypto/asymmetric_keys/public_key.c | 32 +++ crypto/asymmetric_keys/rsa.c | 283 +++++++++++++++++++++++++-- crypto/asymmetric_keys/signature.c | 28 +++ include/crypto/public_key.h | 28 +++ include/keys/asymmetric-subtype.h | 6 + include/linux/cred.h | 2 + include/linux/efi.h | 1 + include/uapi/linux/capability.h | 6 +- kernel/cred.c | 17 ++ kernel/power/Kconfig | 62 ++++++- kernel/power/Makefile | 1 + kernel/power/hibernate.c | 42 ++++ kernel/power/hibernate_keys.c | 262 ++++++++++++++++++++++++ kernel/power/main.c | 11 +- kernel/power/power.h | 27 +++ kernel/power/snapshot.c | 299 +++++++++++++++++++++++++++- kernel/power/swap.c | 18 ++ kernel/power/user.c | 24 +++ 32 files changed, 1611 insertions(+), 24 deletions(-) create mode 100644 crypto/asymmetric_keys/pkcs8.asn1 create mode 100644 crypto/asymmetric_keys/pkcs8_info_parser.c create mode 100644 crypto/asymmetric_keys/pkcs8_parser.h create mode 100644 crypto/asymmetric_keys/pkcs8_private_key.c create mode 100644 crypto/asymmetric_keys/pkcs8_rsakey.asn1 create mode 100644 crypto/asymmetric_keys/private_key.h create mode 100644 kernel/power/hibernate_keys.c -- To unsubscribe, e-mail: opensuse-kernel+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-kernel+owner@opensuse.org
Add generate_signature interface on signature.c, asymmetric-subtype and
rsa.c for prepare to implement signature generation.
Signed-off-by: Lee, Chun-Yi
Implement EMSA_PKCS1-v1_5-ENCODE [RFC3447 sec 9.2] in rsa.c. It's the
first step of signature generation operation (RSASSA-PKCS1-v1_5-SIGN).
This patch is temporary set emLen to pks->k, and temporary set EM to
pks->S for debugging. We will replace the above values to real signature
after implement RSASP1.
Signed-off-by: Lee, Chun-Yi
Due to RSA_I2OSP is not only used by signature verification path but also used
in signature generation path. So, separate the length checking of octet string
because it's not for generate 0x00 0x01 leading string when used in signature
generation.
Signed-off-by: Lee, Chun-Yi
Implement Octet String to Integer conversion [RFC3447 sec 4.2] in rsa.c. It's
the second step of signature generation operation.
This patch is temporary set non-RSASP1 message to pks->S for debugging.
Signed-off-by: Lee, Chun-Yi
Implement RSASP1 and fill-in the following data to public key signature
structure: signature length (pkcs->k), signature octet
strings (pks->S) and MPI of signature (pks->rsa.s).
Signed-off-by: Lee, Chun-Yi
Add ASN.1 files and parser to support parsing PKCS #8 private key
information. It's better then direct parsing pure private key because
PKCS #8 has a privateKeyAlgorithm to indicate the algorithm of private
key, e.g. RSA from PKCS #1
Signed-off-by: Lee, Chun-Yi
Per PKCS1 spec, the EMSA-PKCS1-v1_5 encoded message is leading by 0x00 0x01 in
its first 2 bytes. The leading zero byte is suppressed by MPI so we pass a
pointer to the _preceding_ byte to RSA_verify() in original code, but it has
risk for the byte is not zero because it's not in EM buffer's scope, neither
RSA_verify() nor mpi_get_buffer() didn't take care the leading byte.
To avoid the risk, that's better we explicitly add the leading zero byte to EM
for pass to RSA_verify(). This patch allocate a _EM buffer to capture the
result from RSA_I2OSP(), then set the first byte to zero in EM and copy the
remaining bytes from _EM.
Signed-off-by: Lee, Chun-Yi
From: Matthew Garrett
On Fri, Aug 09, 2013 at 12:37:45PM +0800, Lee, Chun-Yi wrote:
From: Matthew Garrett
Secure boot adds certain policy requirements, including that root must not be able to do anything that could cause the kernel to execute arbitrary code. The simplest way to handle this would seem to be to add a new capability and gate various functionality on that. We'll then strip it from the initial capability set if required.
Signed-off-by: Matthew Garrett
Acked-by: Lee, Chun-Yi --- include/uapi/linux/capability.h | 6 +++++-
I know this has been submitted upstream, do you know what the status of it being accepted it? Oh, and nice job on this whole patchset. I might not agree that it's something we should care about, but some people might, so the option to have it is nice. thanks, greg k-h -- To unsubscribe, e-mail: opensuse-kernel+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-kernel+owner@opensuse.org
On Thu, Aug 08, 2013 at 09:48:45PM -0700, Greg KH wrote:
On Fri, Aug 09, 2013 at 12:37:45PM +0800, Lee, Chun-Yi wrote:
From: Matthew Garrett
Secure boot adds certain policy requirements, including that root must not be able to do anything that could cause the kernel to execute arbitrary code. The simplest way to handle this would seem to be to add a new capability and gate various functionality on that. We'll then strip it from the initial capability set if required.
Signed-off-by: Matthew Garrett
Acked-by: Lee, Chun-Yi --- include/uapi/linux/capability.h | 6 +++++- I know this has been submitted upstream, do you know what the status of it being accepted it?
It's run into the problem that capabilities are, broadly, unusable. Adding a new capability means adding new capability checks for fairly obvious reasons. But existing capability-aware applications will drop all privileges except the ones they know they need, which means they won't have the new capability and so fail the new capability checks. This means it's effectively impossible to add a new capability outside a small number of corner cases - it's fine adding capabilities to let you do things you can't currently do, but removing privileges just breaks things. So, despite the fact that I'm the one who proposed this originally, I don't think it's a viable approach. So what are the other options? We can add if (secure_boot) guards, but it's been made clear that people want something that has general benefit rather than being special-cased. All I've really been able to come up with is implementing a BSD-like securelevel. I hear the 90s are this decade's 80s. -- Matthew Garrett | mjg59@srcf.ucam.org -- To unsubscribe, e-mail: opensuse-kernel+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-kernel+owner@opensuse.org
於 四,2013-08-08 於 21:48 -0700,Greg KH 提到:
On Fri, Aug 09, 2013 at 12:37:45PM +0800, Lee, Chun-Yi wrote:
From: Matthew Garrett
Secure boot adds certain policy requirements, including that root must not be able to do anything that could cause the kernel to execute arbitrary code. The simplest way to handle this would seem to be to add a new capability and gate various functionality on that. We'll then strip it from the initial capability set if required.
Signed-off-by: Matthew Garrett
Acked-by: Lee, Chun-Yi --- include/uapi/linux/capability.h | 6 +++++- I know this has been submitted upstream, do you know what the status of it being accepted it?
As I know this patch and derivative patches are still pending on upstream.
Oh, and nice job on this whole patchset. I might not agree that it's something we should care about, but some people might, so the option to have it is nice.
thanks,
greg k-h
I understood! Thanks for your quick response! Joey Lee -- To unsubscribe, e-mail: opensuse-kernel+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-kernel+owner@opensuse.org
From: Josh Boyer
From: Matthew Garrett
Introduced a hibernate_key.c file to query the key pair from EFI variables
and maintain key pair for check signature of S4 snapshot image. We
loaded the private key when snapshot image stored success.
This patch introduced 2 EFI variables for store the key to sign S4 image and
verify signature when S4 wake up. The names and GUID are:
S4SignKey-fe141863-c070-478e-b8a3-878a5dc9ef21
S4WakeKey-fe141863-c070-478e-b8a3-878a5dc9ef21
S4SignKey is used by EFI bootloader to pass the RSA private key that packaged
by PKCS#8 format, kernel will read and parser it when system boot and reload
it when S4 resume. EFI bootloader need gnerate a new private key when every
time system boot.
S4WakeKey is used to pass the RSA public key that packaged by X.509
certificate, kernel will read and parser it for check the signature of
S4 snapshot image when S4 resume.
The follow-up patch will remove S4SignKey and S4WakeKey after load them
to kernel for avoid anyone can access it through efivarfs.
v2:
Add CONFIG_SNAPSHOT_VERIFICATION for build of hibernate_keys.c depend on
Kconfig.
Signed-off-by: Lee, Chun-Yi
This patch add the code for generate/verify signature of snapshot, it
put the signature to snapshot header. This approach can support both
on userspace hibernate and in-kernel hibernate.
Signed-off-by: Lee, Chun-Yi
This patch add swsusp_page_is_sign_key() method to hibernate_key.c and
check the page is S4 sign key data when collect saveable page in
snapshot.c to avoid sign key data included in snapshot image.
Signed-off-by: Lee, Chun-Yi
This patch fix the race condition of remove S4 sign key. It moved the
code of reload sign key to software_resume() in hibernate.c after we
confirmed the snapshot image doesn't in swap partition. We ignore the
errors, -ENOENT, -ENODEV and -NENXIO to ignore the checking result before
swap partition available. It avoid the S4 sign key removed before we
load it after S4 resume success.
Signed-off-by: Lee, Chun-Yi
This patch applied SNAPSHOT_VERIFICATION kernel config for switching
signature check of hibernate snapshot image.
v2:
Moved CONFIG_SNAPSHOT_VERIFICATION to earlier patch.
Signed-off-by: Lee, Chun-Yi
In current solution, the snapshot signature check used the RSA key-pair
that are generated by bootloader(e.g. shim) and pass the key-pair to
kernel through EFI variables. I choice to binding the snapshot
signature check mechanism with UEFI secure boot for provide stronger
protection of hibernate. Current behavior is following:
+ UEFI Secure Boot ON, Kernel found key-pair from shim:
Will do the S4 signature check.
+ UEFI Secure Boot ON, Kernel didn't find key-pair from shim:
Will lock down S4 function.
+ UEFI Secure Boot OFF
Will NOT do the S4 signature check.
Ignore any keys from bootloader.
Signed-off-by: Lee, Chun-Yi
Show the verification time for monitor the performance of SHA256 and RSA
verification.
Signed-off-by: Lee, Chun-Yi
This patch introduced SNAPSHOT_SIG_HASH config for user to select which
hash algorithm will be used during signature generation of snapshot.
Signed-off-by: Lee, Chun-Yi
On Fri, Aug 09, 2013 at 12:37:37PM +0800, Lee, Chun-Yi wrote:
+ When machine resume from hibernate: - EFI bootloader should copy the public key from boottime variable to S4WakeKey EFI variable. - Bootloader need generated a new key-pair for next round S4 usage. It should put new privat ekey to S4SignKey variable.
So, first, this is brilliant. Thank you for putting the work into this. The only potential problem is the generation of a new key pair on every reboot. Some hardware vendors have expressed concerns about writing variables on every boot, so if we can avoid that somehow then life would probably be better. Options for that would seem to be (1) set a flag on S4 and only regenerate keys if that flag has been set (although I need to think about the security considerations of that), or (2) use a magic GUID space that all kernels (including Windows) refuse to expose to userspace. (2) is obviously conditional upon Microsoft, but let's have a chat with them to see if there's already some special-casing in Windows. It wouldn't surprise me. I'll review the rest of these over the next few days. I've been gradually merging in the shim changes to upstream, so do feel free to send me a pull request for the S4 stuff there, too. -- Matthew Garrett | mjg59@srcf.ucam.org -- To unsubscribe, e-mail: opensuse-kernel+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-kernel+owner@opensuse.org
於 五,2013-08-09 於 06:12 +0100,Matthew Garrett 提到:
On Fri, Aug 09, 2013 at 12:37:37PM +0800, Lee, Chun-Yi wrote:
+ When machine resume from hibernate: - EFI bootloader should copy the public key from boottime variable to S4WakeKey EFI variable. - Bootloader need generated a new key-pair for next round S4 usage. It should put new privat ekey to S4SignKey variable.
So, first, this is brilliant. Thank you for putting the work into this.
Thanks for your quick response!
The only potential problem is the generation of a new key pair on every reboot. Some hardware vendors have expressed concerns about writing variables on every boot, so if we can avoid that somehow then life would probably be better.
Do they concern the life of flash memory? or concern to brick the machine because garbage collection don't trigger?
Options for that would seem to be (1) set a flag on S4 and only regenerate keys if that flag has been set (although I need to think about the security considerations of that), or (2) use a magic GUID space that all kernels (including Windows) refuse to expose to userspace. (2) is obviously conditional upon Microsoft, but let's have a chat with them to see if there's already some special-casing in Windows. It wouldn't surprise me.
I discussed with Gary for the behavior to trigger key-pair regeneration in shim. There have another thinking is: Kernel load the S4 sign key (private key) before kernel call ExitBootServices(), load it from boot-time variable. In this case, shim don't need put the private key to NV-runtime variable, so any other OS could not access the key except the window period before ExitBootServices(). And, we write a tag when hibernate to tell shim regenerate key-pair for next round S4. But, above approach means S4 signature check function limit on EFI stub kernel. User can not enable this function without using EFI stub.
I'll review the rest of these over the next few days. I've been gradually merging in the shim changes to upstream, so do feel free to send me a pull request for the S4 stuff there, too.
-- Matthew Garrett | mjg59@srcf.ucam.org
Thanks for your time to review! Joey Lee -- To unsubscribe, e-mail: opensuse-kernel+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-kernel+owner@opensuse.org
On Fri, Aug 09, 2013 at 02:49:44PM +0800, joeyli wrote:
於 五,2013-08-09 於 06:12 +0100,Matthew Garrett 提到:
The only potential problem is the generation of a new key pair on every reboot. Some hardware vendors have expressed concerns about writing variables on every boot, so if we can avoid that somehow then life would probably be better.
Do they concern the life of flash memory? or concern to brick the machine because garbage collection don't trigger?
Yeah, I think the concern is wear cycles.
Kernel load the S4 sign key (private key) before kernel call ExitBootServices(), load it from boot-time variable.
That sounds like a good plan.
But, above approach means S4 signature check function limit on EFI stub kernel. User can not enable this function without using EFI stub.
Personally, I don't have a problem with that - I think using the EFI entry point is the right thing to do, especially since you need to build the kernel with EFI stub support in order to sign it. But in that case, I should really work on getting the grub support for that upstream. -- Matthew Garrett | mjg59@srcf.ucam.org -- To unsubscribe, e-mail: opensuse-kernel+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-kernel+owner@opensuse.org
於 五,2013-08-09 於 08:10 +0100,Matthew Garrett 提到:
On Fri, Aug 09, 2013 at 02:49:44PM +0800, joeyli wrote:
於 五,2013-08-09 於 06:12 +0100,Matthew Garrett 提到:
The only potential problem is the generation of a new key pair on every reboot. Some hardware vendors have expressed concerns about writing variables on every boot, so if we can avoid that somehow then life would probably be better.
Do they concern the life of flash memory? or concern to brick the machine because garbage collection don't trigger?
Yeah, I think the concern is wear cycles.
Kernel load the S4 sign key (private key) before kernel call ExitBootServices(), load it from boot-time variable.
That sounds like a good plan.
But, above approach means S4 signature check function limit on EFI stub kernel. User can not enable this function without using EFI stub.
Personally, I don't have a problem with that - I think using the EFI entry point is the right thing to do, especially since you need to build the kernel with EFI stub support in order to sign it. But in that case, I should really work on getting the grub support for that upstream.
Thanks for your suggestion, then I will try the approach to load private key in EFI stub. Joey Lee -- To unsubscribe, e-mail: opensuse-kernel+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-kernel+owner@opensuse.org
On Fri, 9 Aug 2013, Lee, Chun-Yi wrote:
Hi experts,
This patchset is the implementation for signature verification of hibernate snapshot image. The origin idea is from Jiri Kosina: Let EFI bootloader generate key-pair in UEFI secure boot environment, then pass it to kernel for sign/verify S4 image.
Due to there have potential threat from the S4 image hacked, it may cause SUSE lost the trust in UEFI secure boot. The hacker attack the S4 snapshot image in swap partition through whatever exploit from another trusted OS, an the exploit may don't need physical access machine.
So, this patchset give the ability to kernel for parsing the RSA key-pair from EFI bootloader, then using the private key to generate the signature of S4 snapshot image. Kernel put the signature to snapshot header, then verify the signature when kernel try to recover snapshot image to memory.
Joey,
thanks a lot for all the efforts, good job. I have finally finished going
through all this. Please feel free to add
Reviewed-by: Jiri Kosina
於 五,2013-08-09 於 09:53 +0200,Jiri Kosina 提到:
On Fri, 9 Aug 2013, Lee, Chun-Yi wrote:
Hi experts,
This patchset is the implementation for signature verification of hibernate snapshot image. The origin idea is from Jiri Kosina: Let EFI bootloader generate key-pair in UEFI secure boot environment, then pass it to kernel for sign/verify S4 image.
Due to there have potential threat from the S4 image hacked, it may cause SUSE lost the trust in UEFI secure boot. The hacker attack the S4 snapshot image in swap partition through whatever exploit from another trusted OS, an the exploit may don't need physical access machine.
So, this patchset give the ability to kernel for parsing the RSA key-pair from EFI bootloader, then using the private key to generate the signature of S4 snapshot image. Kernel put the signature to snapshot header, then verify the signature when kernel try to recover snapshot image to memory.
Joey,
thanks a lot for all the efforts, good job. I have finally finished going through all this. Please feel free to add
Reviewed-by: Jiri Kosina
-- Jiri Kosina SUSE Labs
Thanks a lot for your review! Joey Lee -- To unsubscribe, e-mail: opensuse-kernel+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-kernel+owner@opensuse.org
participants (5)
-
Greg KH
-
Jiri Kosina
-
joeyli
-
Lee, Chun-Yi
-
Matthew Garrett