From patchwork Wed Jul 18 16:39:54 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chen Yu X-Patchwork-Id: 10532941 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 66393600F4 for ; Wed, 18 Jul 2018 16:34:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 57573296F1 for ; Wed, 18 Jul 2018 16:34:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4AEFF29702; Wed, 18 Jul 2018 16:34:22 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A729E29611 for ; Wed, 18 Jul 2018 16:34:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731573AbeGRRNC (ORCPT ); Wed, 18 Jul 2018 13:13:02 -0400 Received: from mga04.intel.com ([192.55.52.120]:51996 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731570AbeGRRNC (ORCPT ); Wed, 18 Jul 2018 13:13:02 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 18 Jul 2018 09:34:19 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,371,1526367600"; d="scan'208";a="57520063" Received: from sandybridge-desktop.sh.intel.com ([10.239.160.116]) by orsmga007.jf.intel.com with ESMTP; 18 Jul 2018 09:34:09 -0700 From: Chen Yu To: linux-pm@vger.kernel.org Cc: Rui Zhang , "Gu, Kookoo" , Chen Yu , "Rafael J . Wysocki" , Pavel Machek , Len Brown , "Lee, Chun-Yi" , Eric Biggers , "Theodore Ts'o" , Stephan Mueller , Denis Kenzior , linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 2/4][RFC v2] PM / hibernate: Install crypto hooks for hibernation encryption Date: Thu, 19 Jul 2018 00:39:54 +0800 Message-Id: X-Mailer: git-send-email 2.7.4 In-Reply-To: References: Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The encryption helper functions are installed into hibernation framework for later use. Suggested-by: Rafael J. Wysocki Cc: Rafael J. Wysocki Cc: Pavel Machek Cc: Len Brown Cc: "Lee, Chun-Yi" Cc: Eric Biggers Cc: "Theodore Ts'o" Cc: Stephan Mueller Cc: Denis Kenzior Cc: linux-pm@vger.kernel.org Cc: linux-crypto@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Chen Yu --- include/linux/suspend.h | 40 +++++++++++++++++++++++ kernel/power/crypto_hibernation.c | 10 ++++++ kernel/power/hibernate.c | 67 +++++++++++++++++++++++++++++++++++++++ kernel/power/power.h | 2 ++ 4 files changed, 119 insertions(+) diff --git a/include/linux/suspend.h b/include/linux/suspend.h index 440b62f..b45a857 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -391,6 +391,46 @@ extern void hibernation_set_ops(const struct platform_hibernation_ops *ops); extern int hibernate(void); extern bool system_entering_hibernation(void); extern bool hibernation_available(void); +#if IS_ENABLED(CONFIG_CRYPTO_HIBERNATION) +struct hibernation_crypto_ops { + int (*crypto_data)( + const char *inbuf, int inlen, + char *outbuf, int outlen, + unsigned int cmd, + int page_idx); + void (*save)(void *buf); + void (*restore)(void *buf); + int (*init)(bool suspend); +}; + +extern void hibernation_set_crypto_ops( + const struct hibernation_crypto_ops *ops); +extern int hibernation_crypto_data( + const char *inbuf, + int inlen, + char *outbuf, + int outlen, + unsigned int cmd, + int page_idx); +extern void hibernation_crypto_save(void *outbuf); +extern void hibernation_crypto_restore(void *inbuf); +extern int hibernation_crypto_init(bool suspend); +extern int hibernation_crypto_mode; +#else +static inline int hibernation_crypto_data( + const char *inbuf, + int inlen, + char *outbuf, + int outlen, + unsigned int cmd, + int page_idx) { return 0; } +static inline void hibernation_crypto_save(void *outbuf) {} +static inline void hibernation_crypto_restore(void *inbuf) {} +static inline int hibernation_crypto_init(bool suspend) +{ + return 0; +} +#endif asmlinkage int swsusp_save(void); extern struct pbe *restore_pblist; #else /* CONFIG_HIBERNATION */ diff --git a/kernel/power/crypto_hibernation.c b/kernel/power/crypto_hibernation.c index 406bb0c..845eb54 100644 --- a/kernel/power/crypto_hibernation.c +++ b/kernel/power/crypto_hibernation.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -288,6 +289,13 @@ static int crypto_init(bool suspend) return 0; } +static const struct hibernation_crypto_ops crypto_ops = { + .crypto_data = crypto_data, + .save = crypto_save, + .restore = crypto_restore, + .init = crypto_init, +}; + /* key/salt probing via ioctl. */ dev_t crypto_dev; static struct class *crypto_dev_class; @@ -384,6 +392,8 @@ static int crypto_hibernate_init(void) /* generate the random salt */ get_random_bytes(get_salt_ptr(), HIBERNATE_MAX_SALT_BYTES); + hibernation_set_crypto_ops(&crypto_ops); + return 0; r_device: diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 9c85c78..a9e82f8 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -59,6 +59,16 @@ enum { /* keep last */ __HIBERNATION_AFTER_LAST }; + +#if IS_ENABLED(CONFIG_CRYPTO_HIBERNATION) +enum { + HIBERNATION_ENCRYPT, + HIBERNATION_SIGNATURE, + HIBERNATION_ENCRYPT_SIGNATURE, +}; +int hibernation_crypto_mode = HIBERNATION_ENCRYPT; +#endif + #define HIBERNATION_MAX (__HIBERNATION_AFTER_LAST-1) #define HIBERNATION_FIRST (HIBERNATION_INVALID + 1) @@ -96,6 +106,63 @@ void hibernation_set_ops(const struct platform_hibernation_ops *ops) } EXPORT_SYMBOL_GPL(hibernation_set_ops); +#if IS_ENABLED(CONFIG_CRYPTO_HIBERNATION) +/* Install encryption/decryption/signature hooks. */ +static const struct hibernation_crypto_ops *hibernation_crypto_ops; + +void hibernation_set_crypto_ops(const struct hibernation_crypto_ops *ops) +{ + hibernation_crypto_ops = ops; +} +EXPORT_SYMBOL_GPL(hibernation_set_crypto_ops); + +int hibernation_crypto_data( + const char *inbuf, + int inlen, + char *outbuf, + int outlen, + unsigned int mode, + int page_idx) +{ + if (hibernation_crypto_ops && + hibernation_crypto_ops->crypto_data) + return hibernation_crypto_ops->crypto_data(inbuf, + inlen, outbuf, outlen, mode, page_idx); + else + return -EINVAL; +} +EXPORT_SYMBOL_GPL(hibernation_crypto_data); + +/* Invoked before hibernate. */ +void hibernation_crypto_save(void *outbuf) +{ + if (hibernation_crypto_ops && + hibernation_crypto_ops->save) + hibernation_crypto_ops->save(outbuf); +} +EXPORT_SYMBOL_GPL(hibernation_crypto_save); + +/* Invoked before resumed. */ +void hibernation_crypto_restore(void *inbuf) +{ + if (hibernation_crypto_ops && + hibernation_crypto_ops->restore) + hibernation_crypto_ops->restore(inbuf); +} +EXPORT_SYMBOL_GPL(hibernation_crypto_restore); + +/* Initialization for crypto helper facilities. */ +int hibernation_crypto_init(bool suspend) +{ + if (hibernation_crypto_ops && + hibernation_crypto_ops->init) + return hibernation_crypto_ops->init(suspend); + else + return -EINVAL; +} +EXPORT_SYMBOL_GPL(hibernation_crypto_init); + +#endif static bool entering_platform_hibernation; bool system_entering_hibernation(void) diff --git a/kernel/power/power.h b/kernel/power/power.h index a539bdb..ba3b24c 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -107,6 +107,8 @@ struct hibernation_crypto { struct hibernation_crypto_keys keys; }; +extern void hibernation_set_crypto_ops( + const struct hibernation_crypto_ops *ops); #else #define HIBERNATE_MAX_SALT_BYTES 0 #endif