From patchwork Tue Aug 13 07:53:00 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sumit Garg X-Patchwork-Id: 11091411 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 05D9814DB for ; Tue, 13 Aug 2019 07:54:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id ECDC1285C7 for ; Tue, 13 Aug 2019 07:54:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DDDF5285EB; Tue, 13 Aug 2019 07:54:04 +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.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,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 BC85D285C7 for ; Tue, 13 Aug 2019 07:54:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727900AbfHMHyB (ORCPT ); Tue, 13 Aug 2019 03:54:01 -0400 Received: from mail-pg1-f195.google.com ([209.85.215.195]:38479 "EHLO mail-pg1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727892AbfHMHyA (ORCPT ); Tue, 13 Aug 2019 03:54:00 -0400 Received: by mail-pg1-f195.google.com with SMTP id e11so265047pga.5 for ; Tue, 13 Aug 2019 00:53:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=XiLT8JJGX9uceLIR/eagArmQGE9PBHPG6APlyqXqF3U=; b=HNBfjmhal70YjiBtzQ8XUCmseT2tpX02DvvqFDMQckJFPPM5ZY0+aqNAv8vDMRw7xE 4X8bAXRYqG5Tuv0qnrpDa+3Wav/45ed7MrxaBBVMBXkswGUJ4R+jV91ADtQIW3FGVjGp 8efgx/1680z/ufTjoQloSQbggUU1h7jvOfEhi0N1/Oxs5xUHkxJ0PCkkQPgSsi8d/xma pCJzkn0MY08ICp6amgdn/CW6M3gG5vFxBxQyX5sckW8YMjcjWogsij9272CYXWP4mtkW XYlwnZL758aXrYRtKoy3VEY/gdZLfHwgS5AwCbgvwvUijQq06vnbdR8uDNW/zz8jtBaP snWw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=XiLT8JJGX9uceLIR/eagArmQGE9PBHPG6APlyqXqF3U=; b=o60Bm2xbNmeyuaPectYNRv1K3D6EKtCtsFNG1bAmYjjCUHilXHEk98Hq5jl/xo/KOC /qiytztyLf3zIahZGv7Xn3IIfAHvJDoq6otZSkf+8wmbrgLscMg38yUKX/Cp/ZbHbSHT Tk69sXBKQHkGhCmf18OW26BEsPmg7rXCmzrf4Cib6ldHslCCcs7e6ZcyQBNJXvz9Whjk JWTJczbPwAkgL9Er0jTS2aeMwh4Zu363WLyV6+TkF5+8w9CKur2F19YMXUHLQjHZMNG9 xR7Ugr9bdi2X7L+gVWMqrJaTvIg5FKQnd2vrpiIlvyOtHaQEs3UaYFp4E9uhCxUBfJt+ YMMw== X-Gm-Message-State: APjAAAVVyxRVSkoK/7KHuqpm+p8ZNn9M6UlJ5jQvWtfckFtJr69WS3YW G6aA5fa3cZ7XBTapxNwJtunugA== X-Google-Smtp-Source: APXvYqy96iD4zwQ1qvdYDG5n2OkOROyT+m9niDT2LDtjEztXvTvTPFgMnRmT70M359weDccESwhs8A== X-Received: by 2002:a17:90a:109:: with SMTP id b9mr986688pjb.112.1565682838995; Tue, 13 Aug 2019 00:53:58 -0700 (PDT) Received: from localhost.localdomain ([45.114.72.100]) by smtp.gmail.com with ESMTPSA id l25sm131462563pff.143.2019.08.13.00.53.46 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 13 Aug 2019 00:53:58 -0700 (PDT) From: Sumit Garg To: keyrings@vger.kernel.org, linux-integrity@vger.kernel.org, linux-crypto@vger.kernel.org, linux-security-module@vger.kernel.org Cc: dhowells@redhat.com, herbert@gondor.apana.org.au, davem@davemloft.net, peterhuewe@gmx.de, jgg@ziepe.ca, jejb@linux.ibm.com, jarkko.sakkinen@linux.intel.com, arnd@arndb.de, gregkh@linuxfoundation.org, zohar@linux.ibm.com, jmorris@namei.org, serge@hallyn.com, casey@schaufler-ca.com, ard.biesheuvel@linaro.org, daniel.thompson@linaro.org, linux-kernel@vger.kernel.org, tee-dev@lists.linaro.org, Sumit Garg Subject: [RFC/RFT v4 1/5] tpm: move tpm_buf code to include/linux/ Date: Tue, 13 Aug 2019 13:23:00 +0530 Message-Id: <1565682784-10234-2-git-send-email-sumit.garg@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1565682784-10234-1-git-send-email-sumit.garg@linaro.org> References: <1565682784-10234-1-git-send-email-sumit.garg@linaro.org> Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP Move tpm_buf code to common include/linux/tpm.h header so that it can be reused via other subsystems like trusted keys etc. Also rename trusted keys TPM 1.x buffer implementation to tpm1_buf to avoid any compilation errors. Suggested-by: Jarkko Sakkinen Signed-off-by: Sumit Garg --- drivers/char/tpm/tpm.h | 214 ------------------------------------------------ include/keys/trusted.h | 12 +-- include/linux/tpm.h | 214 ++++++++++++++++++++++++++++++++++++++++++++++++ security/keys/trusted.c | 12 +-- 4 files changed, 226 insertions(+), 226 deletions(-) diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index e503ffc..0b5498a 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -25,7 +25,6 @@ #include #include #include -#include #include #ifdef CONFIG_X86 @@ -58,123 +57,6 @@ enum tpm_addr { #define TPM_ERR_DISABLED 0x7 #define TPM_ERR_INVALID_POSTINIT 38 -#define TPM_HEADER_SIZE 10 - -enum tpm2_const { - TPM2_PLATFORM_PCR = 24, - TPM2_PCR_SELECT_MIN = ((TPM2_PLATFORM_PCR + 7) / 8), -}; - -enum tpm2_timeouts { - TPM2_TIMEOUT_A = 750, - TPM2_TIMEOUT_B = 2000, - TPM2_TIMEOUT_C = 200, - TPM2_TIMEOUT_D = 30, - TPM2_DURATION_SHORT = 20, - TPM2_DURATION_MEDIUM = 750, - TPM2_DURATION_LONG = 2000, - TPM2_DURATION_LONG_LONG = 300000, - TPM2_DURATION_DEFAULT = 120000, -}; - -enum tpm2_structures { - TPM2_ST_NO_SESSIONS = 0x8001, - TPM2_ST_SESSIONS = 0x8002, -}; - -/* Indicates from what layer of the software stack the error comes from */ -#define TSS2_RC_LAYER_SHIFT 16 -#define TSS2_RESMGR_TPM_RC_LAYER (11 << TSS2_RC_LAYER_SHIFT) - -enum tpm2_return_codes { - TPM2_RC_SUCCESS = 0x0000, - TPM2_RC_HASH = 0x0083, /* RC_FMT1 */ - TPM2_RC_HANDLE = 0x008B, - TPM2_RC_INITIALIZE = 0x0100, /* RC_VER1 */ - TPM2_RC_FAILURE = 0x0101, - TPM2_RC_DISABLED = 0x0120, - TPM2_RC_COMMAND_CODE = 0x0143, - TPM2_RC_TESTING = 0x090A, /* RC_WARN */ - TPM2_RC_REFERENCE_H0 = 0x0910, - TPM2_RC_RETRY = 0x0922, -}; - -enum tpm2_command_codes { - TPM2_CC_FIRST = 0x011F, - TPM2_CC_HIERARCHY_CONTROL = 0x0121, - TPM2_CC_HIERARCHY_CHANGE_AUTH = 0x0129, - TPM2_CC_CREATE_PRIMARY = 0x0131, - TPM2_CC_SEQUENCE_COMPLETE = 0x013E, - TPM2_CC_SELF_TEST = 0x0143, - TPM2_CC_STARTUP = 0x0144, - TPM2_CC_SHUTDOWN = 0x0145, - TPM2_CC_NV_READ = 0x014E, - TPM2_CC_CREATE = 0x0153, - TPM2_CC_LOAD = 0x0157, - TPM2_CC_SEQUENCE_UPDATE = 0x015C, - TPM2_CC_UNSEAL = 0x015E, - TPM2_CC_CONTEXT_LOAD = 0x0161, - TPM2_CC_CONTEXT_SAVE = 0x0162, - TPM2_CC_FLUSH_CONTEXT = 0x0165, - TPM2_CC_VERIFY_SIGNATURE = 0x0177, - TPM2_CC_GET_CAPABILITY = 0x017A, - TPM2_CC_GET_RANDOM = 0x017B, - TPM2_CC_PCR_READ = 0x017E, - TPM2_CC_PCR_EXTEND = 0x0182, - TPM2_CC_EVENT_SEQUENCE_COMPLETE = 0x0185, - TPM2_CC_HASH_SEQUENCE_START = 0x0186, - TPM2_CC_CREATE_LOADED = 0x0191, - TPM2_CC_LAST = 0x0193, /* Spec 1.36 */ -}; - -enum tpm2_permanent_handles { - TPM2_RS_PW = 0x40000009, -}; - -enum tpm2_capabilities { - TPM2_CAP_HANDLES = 1, - TPM2_CAP_COMMANDS = 2, - TPM2_CAP_PCRS = 5, - TPM2_CAP_TPM_PROPERTIES = 6, -}; - -enum tpm2_properties { - TPM_PT_TOTAL_COMMANDS = 0x0129, -}; - -enum tpm2_startup_types { - TPM2_SU_CLEAR = 0x0000, - TPM2_SU_STATE = 0x0001, -}; - -enum tpm2_cc_attrs { - TPM2_CC_ATTR_CHANDLES = 25, - TPM2_CC_ATTR_RHANDLE = 28, -}; - -#define TPM_VID_INTEL 0x8086 -#define TPM_VID_WINBOND 0x1050 -#define TPM_VID_STM 0x104A - -enum tpm_chip_flags { - TPM_CHIP_FLAG_TPM2 = BIT(1), - TPM_CHIP_FLAG_IRQ = BIT(2), - TPM_CHIP_FLAG_VIRTUAL = BIT(3), - TPM_CHIP_FLAG_HAVE_TIMEOUTS = BIT(4), - TPM_CHIP_FLAG_ALWAYS_POWERED = BIT(5), -}; - -#define to_tpm_chip(d) container_of(d, struct tpm_chip, dev) - -struct tpm_header { - __be16 tag; - __be32 length; - union { - __be32 ordinal; - __be32 return_code; - }; -} __packed; - #define TPM_TAG_RQU_COMMAND 193 struct stclear_flags_t { @@ -274,102 +156,6 @@ enum tpm_sub_capabilities { * compiler warnings about stack frame size. */ #define TPM_MAX_RNG_DATA 128 -/* A string buffer type for constructing TPM commands. This is based on the - * ideas of string buffer code in security/keys/trusted.h but is heap based - * in order to keep the stack usage minimal. - */ - -enum tpm_buf_flags { - TPM_BUF_OVERFLOW = BIT(0), -}; - -struct tpm_buf { - struct page *data_page; - unsigned int flags; - u8 *data; -}; - -static inline void tpm_buf_reset(struct tpm_buf *buf, u16 tag, u32 ordinal) -{ - struct tpm_header *head = (struct tpm_header *)buf->data; - - head->tag = cpu_to_be16(tag); - head->length = cpu_to_be32(sizeof(*head)); - head->ordinal = cpu_to_be32(ordinal); -} - -static inline int tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal) -{ - buf->data_page = alloc_page(GFP_HIGHUSER); - if (!buf->data_page) - return -ENOMEM; - - buf->flags = 0; - buf->data = kmap(buf->data_page); - tpm_buf_reset(buf, tag, ordinal); - return 0; -} - -static inline void tpm_buf_destroy(struct tpm_buf *buf) -{ - kunmap(buf->data_page); - __free_page(buf->data_page); -} - -static inline u32 tpm_buf_length(struct tpm_buf *buf) -{ - struct tpm_header *head = (struct tpm_header *)buf->data; - - return be32_to_cpu(head->length); -} - -static inline u16 tpm_buf_tag(struct tpm_buf *buf) -{ - struct tpm_header *head = (struct tpm_header *)buf->data; - - return be16_to_cpu(head->tag); -} - -static inline void tpm_buf_append(struct tpm_buf *buf, - const unsigned char *new_data, - unsigned int new_len) -{ - struct tpm_header *head = (struct tpm_header *)buf->data; - u32 len = tpm_buf_length(buf); - - /* Return silently if overflow has already happened. */ - if (buf->flags & TPM_BUF_OVERFLOW) - return; - - if ((len + new_len) > PAGE_SIZE) { - WARN(1, "tpm_buf: overflow\n"); - buf->flags |= TPM_BUF_OVERFLOW; - return; - } - - memcpy(&buf->data[len], new_data, new_len); - head->length = cpu_to_be32(len + new_len); -} - -static inline void tpm_buf_append_u8(struct tpm_buf *buf, const u8 value) -{ - tpm_buf_append(buf, &value, 1); -} - -static inline void tpm_buf_append_u16(struct tpm_buf *buf, const u16 value) -{ - __be16 value2 = cpu_to_be16(value); - - tpm_buf_append(buf, (u8 *) &value2, 2); -} - -static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value) -{ - __be32 value2 = cpu_to_be32(value); - - tpm_buf_append(buf, (u8 *) &value2, 4); -} - extern struct class *tpm_class; extern struct class *tpmrm_class; extern dev_t tpm_devt; diff --git a/include/keys/trusted.h b/include/keys/trusted.h index 0071298..841ae11 100644 --- a/include/keys/trusted.h +++ b/include/keys/trusted.h @@ -17,7 +17,7 @@ #define LOAD32N(buffer, offset) (*(uint32_t *)&buffer[offset]) #define LOAD16(buffer, offset) (ntohs(*(uint16_t *)&buffer[offset])) -struct tpm_buf { +struct tpm1_buf { int len; unsigned char data[MAX_BUF_SIZE]; }; @@ -46,7 +46,7 @@ int TSS_checkhmac1(unsigned char *buffer, unsigned int keylen, ...); int trusted_tpm_send(unsigned char *cmd, size_t buflen); -int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce); +int oiap(struct tpm1_buf *tb, uint32_t *handle, unsigned char *nonce); #define TPM_DEBUG 0 @@ -110,24 +110,24 @@ static inline void dump_tpm_buf(unsigned char *buf) } #endif -static inline void store8(struct tpm_buf *buf, const unsigned char value) +static inline void store8(struct tpm1_buf *buf, const unsigned char value) { buf->data[buf->len++] = value; } -static inline void store16(struct tpm_buf *buf, const uint16_t value) +static inline void store16(struct tpm1_buf *buf, const uint16_t value) { *(uint16_t *) & buf->data[buf->len] = htons(value); buf->len += sizeof value; } -static inline void store32(struct tpm_buf *buf, const uint32_t value) +static inline void store32(struct tpm1_buf *buf, const uint32_t value) { *(uint32_t *) & buf->data[buf->len] = htonl(value); buf->len += sizeof value; } -static inline void storebytes(struct tpm_buf *buf, const unsigned char *in, +static inline void storebytes(struct tpm1_buf *buf, const unsigned char *in, const int len) { memcpy(buf->data + buf->len, in, len); diff --git a/include/linux/tpm.h b/include/linux/tpm.h index 53c0ea9..130c167 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #define TPM_DIGEST_SIZE 20 /* Max TPM v1.2 PCR size */ @@ -161,6 +162,219 @@ struct tpm_chip { int locality; }; +#define TPM_HEADER_SIZE 10 + +enum tpm2_const { + TPM2_PLATFORM_PCR = 24, + TPM2_PCR_SELECT_MIN = ((TPM2_PLATFORM_PCR + 7) / 8), +}; + +enum tpm2_timeouts { + TPM2_TIMEOUT_A = 750, + TPM2_TIMEOUT_B = 2000, + TPM2_TIMEOUT_C = 200, + TPM2_TIMEOUT_D = 30, + TPM2_DURATION_SHORT = 20, + TPM2_DURATION_MEDIUM = 750, + TPM2_DURATION_LONG = 2000, + TPM2_DURATION_LONG_LONG = 300000, + TPM2_DURATION_DEFAULT = 120000, +}; + +enum tpm2_structures { + TPM2_ST_NO_SESSIONS = 0x8001, + TPM2_ST_SESSIONS = 0x8002, +}; + +/* Indicates from what layer of the software stack the error comes from */ +#define TSS2_RC_LAYER_SHIFT 16 +#define TSS2_RESMGR_TPM_RC_LAYER (11 << TSS2_RC_LAYER_SHIFT) + +enum tpm2_return_codes { + TPM2_RC_SUCCESS = 0x0000, + TPM2_RC_HASH = 0x0083, /* RC_FMT1 */ + TPM2_RC_HANDLE = 0x008B, + TPM2_RC_INITIALIZE = 0x0100, /* RC_VER1 */ + TPM2_RC_FAILURE = 0x0101, + TPM2_RC_DISABLED = 0x0120, + TPM2_RC_COMMAND_CODE = 0x0143, + TPM2_RC_TESTING = 0x090A, /* RC_WARN */ + TPM2_RC_REFERENCE_H0 = 0x0910, + TPM2_RC_RETRY = 0x0922, +}; + +enum tpm2_command_codes { + TPM2_CC_FIRST = 0x011F, + TPM2_CC_HIERARCHY_CONTROL = 0x0121, + TPM2_CC_HIERARCHY_CHANGE_AUTH = 0x0129, + TPM2_CC_CREATE_PRIMARY = 0x0131, + TPM2_CC_SEQUENCE_COMPLETE = 0x013E, + TPM2_CC_SELF_TEST = 0x0143, + TPM2_CC_STARTUP = 0x0144, + TPM2_CC_SHUTDOWN = 0x0145, + TPM2_CC_NV_READ = 0x014E, + TPM2_CC_CREATE = 0x0153, + TPM2_CC_LOAD = 0x0157, + TPM2_CC_SEQUENCE_UPDATE = 0x015C, + TPM2_CC_UNSEAL = 0x015E, + TPM2_CC_CONTEXT_LOAD = 0x0161, + TPM2_CC_CONTEXT_SAVE = 0x0162, + TPM2_CC_FLUSH_CONTEXT = 0x0165, + TPM2_CC_VERIFY_SIGNATURE = 0x0177, + TPM2_CC_GET_CAPABILITY = 0x017A, + TPM2_CC_GET_RANDOM = 0x017B, + TPM2_CC_PCR_READ = 0x017E, + TPM2_CC_PCR_EXTEND = 0x0182, + TPM2_CC_EVENT_SEQUENCE_COMPLETE = 0x0185, + TPM2_CC_HASH_SEQUENCE_START = 0x0186, + TPM2_CC_CREATE_LOADED = 0x0191, + TPM2_CC_LAST = 0x0193, /* Spec 1.36 */ +}; + +enum tpm2_permanent_handles { + TPM2_RS_PW = 0x40000009, +}; + +enum tpm2_capabilities { + TPM2_CAP_HANDLES = 1, + TPM2_CAP_COMMANDS = 2, + TPM2_CAP_PCRS = 5, + TPM2_CAP_TPM_PROPERTIES = 6, +}; + +enum tpm2_properties { + TPM_PT_TOTAL_COMMANDS = 0x0129, +}; + +enum tpm2_startup_types { + TPM2_SU_CLEAR = 0x0000, + TPM2_SU_STATE = 0x0001, +}; + +enum tpm2_cc_attrs { + TPM2_CC_ATTR_CHANDLES = 25, + TPM2_CC_ATTR_RHANDLE = 28, +}; + +#define TPM_VID_INTEL 0x8086 +#define TPM_VID_WINBOND 0x1050 +#define TPM_VID_STM 0x104A + +enum tpm_chip_flags { + TPM_CHIP_FLAG_TPM2 = BIT(1), + TPM_CHIP_FLAG_IRQ = BIT(2), + TPM_CHIP_FLAG_VIRTUAL = BIT(3), + TPM_CHIP_FLAG_HAVE_TIMEOUTS = BIT(4), + TPM_CHIP_FLAG_ALWAYS_POWERED = BIT(5), +}; + +#define to_tpm_chip(d) container_of(d, struct tpm_chip, dev) + +struct tpm_header { + __be16 tag; + __be32 length; + union { + __be32 ordinal; + __be32 return_code; + }; +} __packed; + +/* A string buffer type for constructing TPM commands. This is based on the + * ideas of string buffer code in security/keys/trusted.h but is heap based + * in order to keep the stack usage minimal. + */ + +enum tpm_buf_flags { + TPM_BUF_OVERFLOW = BIT(0), +}; + +struct tpm_buf { + struct page *data_page; + unsigned int flags; + u8 *data; +}; + +static inline void tpm_buf_reset(struct tpm_buf *buf, u16 tag, u32 ordinal) +{ + struct tpm_header *head = (struct tpm_header *)buf->data; + + head->tag = cpu_to_be16(tag); + head->length = cpu_to_be32(sizeof(*head)); + head->ordinal = cpu_to_be32(ordinal); +} + +static inline int tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal) +{ + buf->data_page = alloc_page(GFP_HIGHUSER); + if (!buf->data_page) + return -ENOMEM; + + buf->flags = 0; + buf->data = kmap(buf->data_page); + tpm_buf_reset(buf, tag, ordinal); + return 0; +} + +static inline void tpm_buf_destroy(struct tpm_buf *buf) +{ + kunmap(buf->data_page); + __free_page(buf->data_page); +} + +static inline u32 tpm_buf_length(struct tpm_buf *buf) +{ + struct tpm_header *head = (struct tpm_header *)buf->data; + + return be32_to_cpu(head->length); +} + +static inline u16 tpm_buf_tag(struct tpm_buf *buf) +{ + struct tpm_header *head = (struct tpm_header *)buf->data; + + return be16_to_cpu(head->tag); +} + +static inline void tpm_buf_append(struct tpm_buf *buf, + const unsigned char *new_data, + unsigned int new_len) +{ + struct tpm_header *head = (struct tpm_header *)buf->data; + u32 len = tpm_buf_length(buf); + + /* Return silently if overflow has already happened. */ + if (buf->flags & TPM_BUF_OVERFLOW) + return; + + if ((len + new_len) > PAGE_SIZE) { + WARN(1, "tpm_buf: overflow\n"); + buf->flags |= TPM_BUF_OVERFLOW; + return; + } + + memcpy(&buf->data[len], new_data, new_len); + head->length = cpu_to_be32(len + new_len); +} + +static inline void tpm_buf_append_u8(struct tpm_buf *buf, const u8 value) +{ + tpm_buf_append(buf, &value, 1); +} + +static inline void tpm_buf_append_u16(struct tpm_buf *buf, const u16 value) +{ + __be16 value2 = cpu_to_be16(value); + + tpm_buf_append(buf, (u8 *) &value2, 2); +} + +static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value) +{ + __be32 value2 = cpu_to_be32(value); + + tpm_buf_append(buf, (u8 *) &value2, 4); +} + #if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE) extern int tpm_is_tpm2(struct tpm_chip *chip); diff --git a/security/keys/trusted.c b/security/keys/trusted.c index 9a94672..0736671 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c @@ -395,7 +395,7 @@ static int pcrlock(const int pcrnum) /* * Create an object specific authorisation protocol (OSAP) session */ -static int osap(struct tpm_buf *tb, struct osapsess *s, +static int osap(struct tpm1_buf *tb, struct osapsess *s, const unsigned char *key, uint16_t type, uint32_t handle) { unsigned char enonce[TPM_NONCE_SIZE]; @@ -430,7 +430,7 @@ static int osap(struct tpm_buf *tb, struct osapsess *s, /* * Create an object independent authorisation protocol (oiap) session */ -int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce) +int oiap(struct tpm1_buf *tb, uint32_t *handle, unsigned char *nonce) { int ret; @@ -464,7 +464,7 @@ struct tpm_digests { * Have the TPM seal(encrypt) the trusted key, possibly based on * Platform Configuration Registers (PCRs). AUTH1 for sealing key. */ -static int tpm_seal(struct tpm_buf *tb, uint16_t keytype, +static int tpm_seal(struct tpm1_buf *tb, uint16_t keytype, uint32_t keyhandle, const unsigned char *keyauth, const unsigned char *data, uint32_t datalen, unsigned char *blob, uint32_t *bloblen, @@ -579,7 +579,7 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype, /* * use the AUTH2_COMMAND form of unseal, to authorize both key and blob */ -static int tpm_unseal(struct tpm_buf *tb, +static int tpm_unseal(struct tpm1_buf *tb, uint32_t keyhandle, const unsigned char *keyauth, const unsigned char *blob, int bloblen, const unsigned char *blobauth, @@ -670,7 +670,7 @@ static int tpm_unseal(struct tpm_buf *tb, static int key_seal(struct trusted_key_payload *p, struct trusted_key_options *o) { - struct tpm_buf *tb; + struct tpm1_buf *tb; int ret; tb = kzalloc(sizeof *tb, GFP_KERNEL); @@ -696,7 +696,7 @@ static int key_seal(struct trusted_key_payload *p, static int key_unseal(struct trusted_key_payload *p, struct trusted_key_options *o) { - struct tpm_buf *tb; + struct tpm1_buf *tb; int ret; tb = kzalloc(sizeof *tb, GFP_KERNEL); From patchwork Tue Aug 13 07:53:01 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sumit Garg X-Patchwork-Id: 11091421 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 20869112C for ; Tue, 13 Aug 2019 07:54:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 14C94285C7 for ; Tue, 13 Aug 2019 07:54:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 07409285EB; Tue, 13 Aug 2019 07:54:18 +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.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,RCVD_IN_DNSWL_HI autolearn=unavailable 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 50908285C7 for ; Tue, 13 Aug 2019 07:54:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727555AbfHMHyQ (ORCPT ); Tue, 13 Aug 2019 03:54:16 -0400 Received: from mail-pl1-f196.google.com ([209.85.214.196]:43254 "EHLO mail-pl1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727777AbfHMHyN (ORCPT ); Tue, 13 Aug 2019 03:54:13 -0400 Received: by mail-pl1-f196.google.com with SMTP id 4so41948764pld.10 for ; Tue, 13 Aug 2019 00:54:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=/LDCXgnTbDgwlPQDLk7SsYNcNi/37UGWjEQF7+J/ZYE=; b=r3iP9PNlcM0kO4YJClGM6fwe6D1fs37ubXNz1GmGBEoLJ5tQF7vRq2VYK4DtybDTq7 UtpKrnGXk9qz6fN9pF6jHtg7y7i+uNm30gBprWeCu1vWcwwl6eo32Z51IKeo+I9z4fIE yi6vjFUv2x8HeaETU6FKL3ehtqXUWB0NTvC9MQjYJTEpMP5UpcFSwxSjJpX9mp4DaREy jQLZAHgi+p8VkhOp6P8RtGEu4UxhCRe/LrKxLcymL0IMwhF4S7EZUc3zbuxA/GXJWpSo bEFsi+jXsjclbAAMjyuUEvypg2xR4i+RDwU3nBssaoeDd94bl24Q6wW+cunLN6hKpc/r RQfg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=/LDCXgnTbDgwlPQDLk7SsYNcNi/37UGWjEQF7+J/ZYE=; b=F6jiw3FR+7+d2ST7fbIKYus3oHpqqpv0ZLirQbFu1URdqAk1GPdAaa7V1E6s5VW2+0 ns1idKM3kMhWplZfmyRJJ99BVmzggz66FwXeZJiI+hPAZtiT96ReLR6/AwZAYbNSrk+z rv8NGBfTQsuCBIljj3lqPyy2vTDEiHOsBId7k/8z+qH0SB9yKTArqpaopps87Q1RRez/ fg5KjMBgAY2wa4fIwrdbrJ87HPtVcpWVm+fVLqzFaactkuY1SFrWGkOoFnb9YdHyBMwe OfjGAn54KDA7vboOFkxTMpTkX5yn76Z4rniN/kEjS+7LWIrDUG8Ttqjb3e7k5p7N4+qT dW0g== X-Gm-Message-State: APjAAAVoUNhqqS6aq+/KpygWWvLMl87pOfRRGW/jJ6zrmq2KlN4/07fy NNaTjCTO22rUz76PKatvTLefFQ== X-Google-Smtp-Source: APXvYqwsbeExH/nr+zaEx9TScTxEo/nl1s4NPJ89pIYFr06y4gHh2Z1IbKyPNOATwEh9lXJ3a1cgHg== X-Received: by 2002:a17:902:883:: with SMTP id 3mr2354968pll.318.1565682852238; Tue, 13 Aug 2019 00:54:12 -0700 (PDT) Received: from localhost.localdomain ([45.114.72.100]) by smtp.gmail.com with ESMTPSA id l25sm131462563pff.143.2019.08.13.00.54.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 13 Aug 2019 00:54:11 -0700 (PDT) From: Sumit Garg To: keyrings@vger.kernel.org, linux-integrity@vger.kernel.org, linux-crypto@vger.kernel.org, linux-security-module@vger.kernel.org Cc: dhowells@redhat.com, herbert@gondor.apana.org.au, davem@davemloft.net, peterhuewe@gmx.de, jgg@ziepe.ca, jejb@linux.ibm.com, jarkko.sakkinen@linux.intel.com, arnd@arndb.de, gregkh@linuxfoundation.org, zohar@linux.ibm.com, jmorris@namei.org, serge@hallyn.com, casey@schaufler-ca.com, ard.biesheuvel@linaro.org, daniel.thompson@linaro.org, linux-kernel@vger.kernel.org, tee-dev@lists.linaro.org, Sumit Garg Subject: [RFC/RFT v4 2/5] KEYS: trusted: use common tpm_buf for TPM1.x code Date: Tue, 13 Aug 2019 13:23:01 +0530 Message-Id: <1565682784-10234-3-git-send-email-sumit.garg@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1565682784-10234-1-git-send-email-sumit.garg@linaro.org> References: <1565682784-10234-1-git-send-email-sumit.garg@linaro.org> Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP Utilize common heap based tpm_buf code for TPM1.x trusted keys rather than using stack based tpm1_buf code. Also, remove tpm1_buf code. Suggested-by: Jarkko Sakkinen Signed-off-by: Sumit Garg Reviewed-by: Jarkko Sakkinen --- include/keys/trusted.h | 37 +------------------ security/keys/trusted.c | 98 ++++++++++++++++++++++--------------------------- 2 files changed, 44 insertions(+), 91 deletions(-) diff --git a/include/keys/trusted.h b/include/keys/trusted.h index 841ae11..29e3e9b 100644 --- a/include/keys/trusted.h +++ b/include/keys/trusted.h @@ -5,10 +5,6 @@ /* implementation specific TPM constants */ #define MAX_BUF_SIZE 1024 #define TPM_GETRANDOM_SIZE 14 -#define TPM_OSAP_SIZE 36 -#define TPM_OIAP_SIZE 10 -#define TPM_SEAL_SIZE 87 -#define TPM_UNSEAL_SIZE 104 #define TPM_SIZE_OFFSET 2 #define TPM_RETURN_OFFSET 6 #define TPM_DATA_OFFSET 10 @@ -17,13 +13,6 @@ #define LOAD32N(buffer, offset) (*(uint32_t *)&buffer[offset]) #define LOAD16(buffer, offset) (ntohs(*(uint16_t *)&buffer[offset])) -struct tpm1_buf { - int len; - unsigned char data[MAX_BUF_SIZE]; -}; - -#define INIT_BUF(tb) (tb->len = 0) - struct osapsess { uint32_t handle; unsigned char secret[SHA1_DIGEST_SIZE]; @@ -46,7 +35,7 @@ int TSS_checkhmac1(unsigned char *buffer, unsigned int keylen, ...); int trusted_tpm_send(unsigned char *cmd, size_t buflen); -int oiap(struct tpm1_buf *tb, uint32_t *handle, unsigned char *nonce); +int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce); #define TPM_DEBUG 0 @@ -109,28 +98,4 @@ static inline void dump_tpm_buf(unsigned char *buf) { } #endif - -static inline void store8(struct tpm1_buf *buf, const unsigned char value) -{ - buf->data[buf->len++] = value; -} - -static inline void store16(struct tpm1_buf *buf, const uint16_t value) -{ - *(uint16_t *) & buf->data[buf->len] = htons(value); - buf->len += sizeof value; -} - -static inline void store32(struct tpm1_buf *buf, const uint32_t value) -{ - *(uint32_t *) & buf->data[buf->len] = htonl(value); - buf->len += sizeof value; -} - -static inline void storebytes(struct tpm1_buf *buf, const unsigned char *in, - const int len) -{ - memcpy(buf->data + buf->len, in, len); - buf->len += len; -} #endif diff --git a/security/keys/trusted.c b/security/keys/trusted.c index 0736671..f7134d6 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c @@ -395,7 +395,7 @@ static int pcrlock(const int pcrnum) /* * Create an object specific authorisation protocol (OSAP) session */ -static int osap(struct tpm1_buf *tb, struct osapsess *s, +static int osap(struct tpm_buf *tb, struct osapsess *s, const unsigned char *key, uint16_t type, uint32_t handle) { unsigned char enonce[TPM_NONCE_SIZE]; @@ -406,13 +406,10 @@ static int osap(struct tpm1_buf *tb, struct osapsess *s, if (ret != TPM_NONCE_SIZE) return ret; - INIT_BUF(tb); - store16(tb, TPM_TAG_RQU_COMMAND); - store32(tb, TPM_OSAP_SIZE); - store32(tb, TPM_ORD_OSAP); - store16(tb, type); - store32(tb, handle); - storebytes(tb, ononce, TPM_NONCE_SIZE); + tpm_buf_reset(tb, TPM_TAG_RQU_COMMAND, TPM_ORD_OSAP); + tpm_buf_append_u16(tb, type); + tpm_buf_append_u32(tb, handle); + tpm_buf_append(tb, ononce, TPM_NONCE_SIZE); ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE); if (ret < 0) @@ -430,17 +427,14 @@ static int osap(struct tpm1_buf *tb, struct osapsess *s, /* * Create an object independent authorisation protocol (oiap) session */ -int oiap(struct tpm1_buf *tb, uint32_t *handle, unsigned char *nonce) +int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce) { int ret; if (!chip) return -ENODEV; - INIT_BUF(tb); - store16(tb, TPM_TAG_RQU_COMMAND); - store32(tb, TPM_OIAP_SIZE); - store32(tb, TPM_ORD_OIAP); + tpm_buf_reset(tb, TPM_TAG_RQU_COMMAND, TPM_ORD_OIAP); ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE); if (ret < 0) return ret; @@ -464,7 +458,7 @@ struct tpm_digests { * Have the TPM seal(encrypt) the trusted key, possibly based on * Platform Configuration Registers (PCRs). AUTH1 for sealing key. */ -static int tpm_seal(struct tpm1_buf *tb, uint16_t keytype, +static int tpm_seal(struct tpm_buf *tb, uint16_t keytype, uint32_t keyhandle, const unsigned char *keyauth, const unsigned char *data, uint32_t datalen, unsigned char *blob, uint32_t *bloblen, @@ -535,20 +529,17 @@ static int tpm_seal(struct tpm1_buf *tb, uint16_t keytype, goto out; /* build and send the TPM request packet */ - INIT_BUF(tb); - store16(tb, TPM_TAG_RQU_AUTH1_COMMAND); - store32(tb, TPM_SEAL_SIZE + pcrinfosize + datalen); - store32(tb, TPM_ORD_SEAL); - store32(tb, keyhandle); - storebytes(tb, td->encauth, SHA1_DIGEST_SIZE); - store32(tb, pcrinfosize); - storebytes(tb, pcrinfo, pcrinfosize); - store32(tb, datalen); - storebytes(tb, data, datalen); - store32(tb, sess.handle); - storebytes(tb, td->nonceodd, TPM_NONCE_SIZE); - store8(tb, cont); - storebytes(tb, td->pubauth, SHA1_DIGEST_SIZE); + tpm_buf_reset(tb, TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_SEAL); + tpm_buf_append_u32(tb, keyhandle); + tpm_buf_append(tb, td->encauth, SHA1_DIGEST_SIZE); + tpm_buf_append_u32(tb, pcrinfosize); + tpm_buf_append(tb, pcrinfo, pcrinfosize); + tpm_buf_append_u32(tb, datalen); + tpm_buf_append(tb, data, datalen); + tpm_buf_append_u32(tb, sess.handle); + tpm_buf_append(tb, td->nonceodd, TPM_NONCE_SIZE); + tpm_buf_append_u8(tb, cont); + tpm_buf_append(tb, td->pubauth, SHA1_DIGEST_SIZE); ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE); if (ret < 0) @@ -579,7 +570,7 @@ static int tpm_seal(struct tpm1_buf *tb, uint16_t keytype, /* * use the AUTH2_COMMAND form of unseal, to authorize both key and blob */ -static int tpm_unseal(struct tpm1_buf *tb, +static int tpm_unseal(struct tpm_buf *tb, uint32_t keyhandle, const unsigned char *keyauth, const unsigned char *blob, int bloblen, const unsigned char *blobauth, @@ -628,20 +619,17 @@ static int tpm_unseal(struct tpm1_buf *tb, return ret; /* build and send TPM request packet */ - INIT_BUF(tb); - store16(tb, TPM_TAG_RQU_AUTH2_COMMAND); - store32(tb, TPM_UNSEAL_SIZE + bloblen); - store32(tb, TPM_ORD_UNSEAL); - store32(tb, keyhandle); - storebytes(tb, blob, bloblen); - store32(tb, authhandle1); - storebytes(tb, nonceodd, TPM_NONCE_SIZE); - store8(tb, cont); - storebytes(tb, authdata1, SHA1_DIGEST_SIZE); - store32(tb, authhandle2); - storebytes(tb, nonceodd, TPM_NONCE_SIZE); - store8(tb, cont); - storebytes(tb, authdata2, SHA1_DIGEST_SIZE); + tpm_buf_reset(tb, TPM_TAG_RQU_AUTH2_COMMAND, TPM_ORD_UNSEAL); + tpm_buf_append_u32(tb, keyhandle); + tpm_buf_append(tb, blob, bloblen); + tpm_buf_append_u32(tb, authhandle1); + tpm_buf_append(tb, nonceodd, TPM_NONCE_SIZE); + tpm_buf_append_u8(tb, cont); + tpm_buf_append(tb, authdata1, SHA1_DIGEST_SIZE); + tpm_buf_append_u32(tb, authhandle2); + tpm_buf_append(tb, nonceodd, TPM_NONCE_SIZE); + tpm_buf_append_u8(tb, cont); + tpm_buf_append(tb, authdata2, SHA1_DIGEST_SIZE); ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE); if (ret < 0) { @@ -670,23 +658,23 @@ static int tpm_unseal(struct tpm1_buf *tb, static int key_seal(struct trusted_key_payload *p, struct trusted_key_options *o) { - struct tpm1_buf *tb; + struct tpm_buf tb; int ret; - tb = kzalloc(sizeof *tb, GFP_KERNEL); - if (!tb) - return -ENOMEM; + ret = tpm_buf_init(&tb, 0, 0); + if (ret) + return ret; /* include migratable flag at end of sealed key */ p->key[p->key_len] = p->migratable; - ret = tpm_seal(tb, o->keytype, o->keyhandle, o->keyauth, + ret = tpm_seal(&tb, o->keytype, o->keyhandle, o->keyauth, p->key, p->key_len + 1, p->blob, &p->blob_len, o->blobauth, o->pcrinfo, o->pcrinfo_len); if (ret < 0) pr_info("trusted_key: srkseal failed (%d)\n", ret); - kzfree(tb); + tpm_buf_destroy(&tb); return ret; } @@ -696,14 +684,14 @@ static int key_seal(struct trusted_key_payload *p, static int key_unseal(struct trusted_key_payload *p, struct trusted_key_options *o) { - struct tpm1_buf *tb; + struct tpm_buf tb; int ret; - tb = kzalloc(sizeof *tb, GFP_KERNEL); - if (!tb) - return -ENOMEM; + ret = tpm_buf_init(&tb, 0, 0); + if (ret) + return ret; - ret = tpm_unseal(tb, o->keyhandle, o->keyauth, p->blob, p->blob_len, + ret = tpm_unseal(&tb, o->keyhandle, o->keyauth, p->blob, p->blob_len, o->blobauth, p->key, &p->key_len); if (ret < 0) pr_info("trusted_key: srkunseal failed (%d)\n", ret); @@ -711,7 +699,7 @@ static int key_unseal(struct trusted_key_payload *p, /* pull migratable flag out of sealed key */ p->migratable = p->key[--p->key_len]; - kzfree(tb); + tpm_buf_destroy(&tb); return ret; } From patchwork Tue Aug 13 07:53:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sumit Garg X-Patchwork-Id: 11091427 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 34F3B1823 for ; Tue, 13 Aug 2019 07:54:32 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2B7C2285E1 for ; Tue, 13 Aug 2019 07:54:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1F6CD285C7; Tue, 13 Aug 2019 07:54:32 +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.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,RCVD_IN_DNSWL_HI autolearn=unavailable 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 B87B6285E1 for ; Tue, 13 Aug 2019 07:54:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727938AbfHMHy0 (ORCPT ); Tue, 13 Aug 2019 03:54:26 -0400 Received: from mail-pf1-f196.google.com ([209.85.210.196]:42450 "EHLO mail-pf1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726810AbfHMHy0 (ORCPT ); Tue, 13 Aug 2019 03:54:26 -0400 Received: by mail-pf1-f196.google.com with SMTP id i30so2416655pfk.9 for ; Tue, 13 Aug 2019 00:54:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=GCl85JKs1gSecc0KTbirVsTaub6OgsM5xbDj1pFTySM=; b=chQd+HUw8fMvGc9VG8day9h5nefxZnRxFm4hphhm2CYpr49nSh/+ev5t9abDXDXZ9l kJMGGDfwB1sg+AQ905NLN2KRacZenYdeEUdA3G13T54twXmQylRjNMFCwoQuNCgHxbWB vxkF15V/LSZ2c8z6AWrp7vPaGMIBbl/kEoCO4rpH7QA+2wiF/ivd1t8fjoEPKxBFW9jF 85a5ISI/Ppj9c0uuHyu8kFWE9qq5p726ukjRCEXFC0VnO+ST6bNi6vf1+E13I6UCv+VR 9PeZozby9tnGwRViTqdAwnRa9HkdY4BQMdtL+L5IFindm9IIXEn+/AQOpv9cCMWJxhrX /L8w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=GCl85JKs1gSecc0KTbirVsTaub6OgsM5xbDj1pFTySM=; b=j/86cjcySfigK/mPTtjxzLBgulbBDwI2q29RCYXFXaPxZTnxLjMHnco55iDIUaG1cI wLXIjooHzXtycujbpXEVBrAryQPUR0yMbA593k8gR9rsBIyNqHPKo4wrdbA8AC5oRbxE kk7UULBwU5VkYNlO6Iq380+WNkUhxLXCcuTxDY09sBxgi/szlZnraPRke18CE0DFqxri TY14/rgk2O1lUkmytGZJyaDt2A8YFIkZ1roFrXCFnSUgUQ2PkC2KckWr43olAIkC3z7w sjeiVx9p7CZO4DIdG72OC1yMtdWIW70UV4eDUivXSGae4oGbhtzvYQgPM6gLn5lUypSw AiqQ== X-Gm-Message-State: APjAAAVEDU2LRwgnbBtL305Fn73m1DK5q4mQXbwQTGQA/h6TbC3FlZaN GtsqTONHRQ/bhRiE04J7MBQbmQ== X-Google-Smtp-Source: APXvYqytDrttQjhBpZiJ0wp89OF686JczpwzkANsCR9yusYQjXkkNjYA/qMPlWv9MWFx3nT7SdRJHQ== X-Received: by 2002:a63:de43:: with SMTP id y3mr33723727pgi.211.1565682865908; Tue, 13 Aug 2019 00:54:25 -0700 (PDT) Received: from localhost.localdomain ([45.114.72.100]) by smtp.gmail.com with ESMTPSA id l25sm131462563pff.143.2019.08.13.00.54.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 13 Aug 2019 00:54:25 -0700 (PDT) From: Sumit Garg To: keyrings@vger.kernel.org, linux-integrity@vger.kernel.org, linux-crypto@vger.kernel.org, linux-security-module@vger.kernel.org Cc: dhowells@redhat.com, herbert@gondor.apana.org.au, davem@davemloft.net, peterhuewe@gmx.de, jgg@ziepe.ca, jejb@linux.ibm.com, jarkko.sakkinen@linux.intel.com, arnd@arndb.de, gregkh@linuxfoundation.org, zohar@linux.ibm.com, jmorris@namei.org, serge@hallyn.com, casey@schaufler-ca.com, ard.biesheuvel@linaro.org, daniel.thompson@linaro.org, linux-kernel@vger.kernel.org, tee-dev@lists.linaro.org, Sumit Garg Subject: [RFC/RFT v4 3/5] KEYS: trusted: create trusted keys subsystem Date: Tue, 13 Aug 2019 13:23:02 +0530 Message-Id: <1565682784-10234-4-git-send-email-sumit.garg@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1565682784-10234-1-git-send-email-sumit.garg@linaro.org> References: <1565682784-10234-1-git-send-email-sumit.garg@linaro.org> Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP Move existing code to trusted keys subsystem. Also, rename files with "tpm" as suffix which provides the underlying implementation. Suggested-by: Jarkko Sakkinen Signed-off-by: Sumit Garg --- crypto/asymmetric_keys/asym_tpm.c | 2 +- include/keys/{trusted.h => trusted_tpm.h} | 4 ++-- security/keys/Makefile | 2 +- security/keys/trusted-keys/Makefile | 7 +++++++ security/keys/{trusted.c => trusted-keys/trusted-tpm.c} | 2 +- 5 files changed, 12 insertions(+), 5 deletions(-) rename include/keys/{trusted.h => trusted_tpm.h} (98%) create mode 100644 security/keys/trusted-keys/Makefile rename security/keys/{trusted.c => trusted-keys/trusted-tpm.c} (99%) diff --git a/crypto/asymmetric_keys/asym_tpm.c b/crypto/asymmetric_keys/asym_tpm.c index 76d2ce3..ec3f309 100644 --- a/crypto/asymmetric_keys/asym_tpm.c +++ b/crypto/asymmetric_keys/asym_tpm.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include diff --git a/include/keys/trusted.h b/include/keys/trusted_tpm.h similarity index 98% rename from include/keys/trusted.h rename to include/keys/trusted_tpm.h index 29e3e9b..9bdf5f4 100644 --- a/include/keys/trusted.h +++ b/include/keys/trusted_tpm.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __TRUSTED_KEY_H -#define __TRUSTED_KEY_H +#ifndef __TRUSTED_TPM_H +#define __TRUSTED_TPM_H /* implementation specific TPM constants */ #define MAX_BUF_SIZE 1024 diff --git a/security/keys/Makefile b/security/keys/Makefile index 9cef540..074f275 100644 --- a/security/keys/Makefile +++ b/security/keys/Makefile @@ -28,5 +28,5 @@ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += keyctl_pkey.o # Key types # obj-$(CONFIG_BIG_KEYS) += big_key.o -obj-$(CONFIG_TRUSTED_KEYS) += trusted.o +obj-$(CONFIG_TRUSTED_KEYS) += trusted-keys/ obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/ diff --git a/security/keys/trusted-keys/Makefile b/security/keys/trusted-keys/Makefile new file mode 100644 index 0000000..4e8963a --- /dev/null +++ b/security/keys/trusted-keys/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for trusted keys +# + +obj-$(CONFIG_TRUSTED_KEYS) += trusted.o +trusted-y += trusted-tpm.o diff --git a/security/keys/trusted.c b/security/keys/trusted-keys/trusted-tpm.c similarity index 99% rename from security/keys/trusted.c rename to security/keys/trusted-keys/trusted-tpm.c index f7134d6..66687e7 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted-keys/trusted-tpm.c @@ -27,7 +27,7 @@ #include #include -#include +#include static const char hmac_alg[] = "hmac(sha1)"; static const char hash_alg[] = "sha1"; From patchwork Tue Aug 13 07:53:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sumit Garg X-Patchwork-Id: 11091431 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 460D514DB for ; Tue, 13 Aug 2019 07:54:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3BB11285C7 for ; Tue, 13 Aug 2019 07:54:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2F180285EB; Tue, 13 Aug 2019 07:54:43 +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.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,RCVD_IN_DNSWL_HI autolearn=unavailable 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 98B70285E1 for ; Tue, 13 Aug 2019 07:54:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727964AbfHMHyk (ORCPT ); Tue, 13 Aug 2019 03:54:40 -0400 Received: from mail-pf1-f193.google.com ([209.85.210.193]:45582 "EHLO mail-pf1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727421AbfHMHyj (ORCPT ); Tue, 13 Aug 2019 03:54:39 -0400 Received: by mail-pf1-f193.google.com with SMTP id w26so5859363pfq.12 for ; Tue, 13 Aug 2019 00:54:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=T/6GszB9sj0hWKj+kaLwjfcR80qoXC6NcpFiphrG3mY=; b=xqQvXFU5pHlQDztbofOSmhKGzz9e0T6Qi0PrUMdcdf/sxw/4v659/OzUPYbEVaqlOm I4lJusOwruYgiFDr0kJxlTuvWJkm7EZ742FZd2eKjokTxLlp4DBh8V/x9xt+b/YQvbbP vImQYrPQW3hxZ5rHqngiqLECJiBC+9tIwMprfwyUw2uFBmlt7w1PsXGW8NaouymODwfq Nd+oCVaqfGzlzdgPZ8nc7UTTEfKsz2IDrZ9VXEqxmkyaPIZv38UOL6BFtG3faI6ijMBm dO/E6BIGq4yXkF01sjBknadFAmqP8yrmeYVsewUuF7DFobVGPsJKzrn3A95gj2sBJeAK VjMg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=T/6GszB9sj0hWKj+kaLwjfcR80qoXC6NcpFiphrG3mY=; b=YtTEhnIkF9NBdKfZB+1Z9d4Qp7Gx1J9g3WNC67+X1cUzlBWQ5jEuOsv0wQlqFxoPS/ JBQqC/0EruClVHKUbxv14weXZT8bIFmv4rFDBHx/z6OhRCGfaFMk1vNumnpjejaETJmw NMjIZbhnGc8Oy08hwK+1GMYMkkwK8/M1+YRPnIAerwRJJ2UnNTl+qUJzoChfOCsw7ZVC 9eierDaARWBDvYoynycngK0DJarC0jBCGXtzwvPqL1xQ7Mhal7N3wluRyprLHnSogsXa dHZCH98OZx4nOR9qtTqTItgTSrOMv1YmC2TOlfptpPKP4Ehjy6y6Xb7YzX0Mnh07Adht /vCw== X-Gm-Message-State: APjAAAVG6fL4lHmTwemkapgXUORk/5sgSbaojMaetGU9qGzoa/lK/esM cc6/BXNojr+LbdakGNjKZWIHKg== X-Google-Smtp-Source: APXvYqw4npY13CrdNPZrCr5nHasYtdWyDa3/334sHsI7QXh/PxIsy93xdqM+wTwaPh7dMFt5Dg7W7g== X-Received: by 2002:a63:6c7:: with SMTP id 190mr33153720pgg.7.1565682878134; Tue, 13 Aug 2019 00:54:38 -0700 (PDT) Received: from localhost.localdomain ([45.114.72.100]) by smtp.gmail.com with ESMTPSA id l25sm131462563pff.143.2019.08.13.00.54.26 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 13 Aug 2019 00:54:37 -0700 (PDT) From: Sumit Garg To: keyrings@vger.kernel.org, linux-integrity@vger.kernel.org, linux-crypto@vger.kernel.org, linux-security-module@vger.kernel.org Cc: dhowells@redhat.com, herbert@gondor.apana.org.au, davem@davemloft.net, peterhuewe@gmx.de, jgg@ziepe.ca, jejb@linux.ibm.com, jarkko.sakkinen@linux.intel.com, arnd@arndb.de, gregkh@linuxfoundation.org, zohar@linux.ibm.com, jmorris@namei.org, serge@hallyn.com, casey@schaufler-ca.com, ard.biesheuvel@linaro.org, daniel.thompson@linaro.org, linux-kernel@vger.kernel.org, tee-dev@lists.linaro.org, Sumit Garg Subject: [RFC/RFT v4 4/5] KEYS: trusted: move tpm2 trusted keys code Date: Tue, 13 Aug 2019 13:23:03 +0530 Message-Id: <1565682784-10234-5-git-send-email-sumit.garg@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1565682784-10234-1-git-send-email-sumit.garg@linaro.org> References: <1565682784-10234-1-git-send-email-sumit.garg@linaro.org> Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP Move TPM2 trusted keys code to trusted keys subsystem. The reason being it's better to consolidate all the trusted keys code to a single location so that it can be maintained sanely. Suggested-by: Jarkko Sakkinen Signed-off-by: Sumit Garg --- drivers/char/tpm/tpm-chip.c | 1 + drivers/char/tpm/tpm-interface.c | 56 ----- drivers/char/tpm/tpm.h | 16 -- drivers/char/tpm/tpm2-cmd.c | 308 +----------------------- include/keys/trusted_tpm.h | 7 + include/linux/tpm.h | 56 +++-- security/keys/trusted-keys/Makefile | 1 + security/keys/trusted-keys/trusted-tpm2.c | 378 ++++++++++++++++++++++++++++++ 8 files changed, 429 insertions(+), 394 deletions(-) create mode 100644 security/keys/trusted-keys/trusted-tpm2.c diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index d47ad10..49450c1 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -243,6 +243,7 @@ struct tpm_chip *tpm_find_get_ops(struct tpm_chip *chip) return NULL; return chip; } +EXPORT_SYMBOL_GPL(tpm_find_get_ops); /** * tpm_dev_release() - free chip memory and the device number diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 1b4f95c..208e5ba 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -454,62 +454,6 @@ int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max) } EXPORT_SYMBOL_GPL(tpm_get_random); -/** - * tpm_seal_trusted() - seal a trusted key payload - * @chip: a &struct tpm_chip instance, %NULL for the default chip - * @options: authentication values and other options - * @payload: the key data in clear and encrypted form - * - * Note: only TPM 2.0 chip are supported. TPM 1.x implementation is located in - * the keyring subsystem. - * - * Return: same as with tpm_transmit_cmd() - */ -int tpm_seal_trusted(struct tpm_chip *chip, struct trusted_key_payload *payload, - struct trusted_key_options *options) -{ - int rc; - - chip = tpm_find_get_ops(chip); - if (!chip || !(chip->flags & TPM_CHIP_FLAG_TPM2)) - return -ENODEV; - - rc = tpm2_seal_trusted(chip, payload, options); - - tpm_put_ops(chip); - return rc; -} -EXPORT_SYMBOL_GPL(tpm_seal_trusted); - -/** - * tpm_unseal_trusted() - unseal a trusted key - * @chip: a &struct tpm_chip instance, %NULL for the default chip - * @options: authentication values and other options - * @payload: the key data in clear and encrypted form - * - * Note: only TPM 2.0 chip are supported. TPM 1.x implementation is located in - * the keyring subsystem. - * - * Return: same as with tpm_transmit_cmd() - */ -int tpm_unseal_trusted(struct tpm_chip *chip, - struct trusted_key_payload *payload, - struct trusted_key_options *options) -{ - int rc; - - chip = tpm_find_get_ops(chip); - if (!chip || !(chip->flags & TPM_CHIP_FLAG_TPM2)) - return -ENODEV; - - rc = tpm2_unseal_trusted(chip, payload, options); - - tpm_put_ops(chip); - - return rc; -} -EXPORT_SYMBOL_GPL(tpm_unseal_trusted); - static int __init tpm_init(void) { int rc; diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 0b5498a..1c07ce6 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -164,8 +164,6 @@ extern const struct file_operations tpmrm_fops; extern struct idr dev_nums_idr; ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz); -ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_buf *buf, - size_t min_rsp_body_length, const char *desc); int tpm_get_timeouts(struct tpm_chip *); int tpm_auto_startup(struct tpm_chip *chip); @@ -192,9 +190,7 @@ static inline void tpm_msleep(unsigned int delay_msec) int tpm_chip_start(struct tpm_chip *chip); void tpm_chip_stop(struct tpm_chip *chip); -struct tpm_chip *tpm_find_get_ops(struct tpm_chip *chip); __must_check int tpm_try_get_ops(struct tpm_chip *chip); -void tpm_put_ops(struct tpm_chip *chip); struct tpm_chip *tpm_chip_alloc(struct device *dev, const struct tpm_class_ops *ops); @@ -214,24 +210,12 @@ static inline void tpm_add_ppi(struct tpm_chip *chip) } #endif -static inline u32 tpm2_rc_value(u32 rc) -{ - return (rc & BIT(7)) ? rc & 0xff : rc; -} - int tpm2_get_timeouts(struct tpm_chip *chip); int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, struct tpm_digest *digest, u16 *digest_size_ptr); int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, struct tpm_digest *digests); int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max); -void tpm2_flush_context(struct tpm_chip *chip, u32 handle); -int tpm2_seal_trusted(struct tpm_chip *chip, - struct trusted_key_payload *payload, - struct trusted_key_options *options); -int tpm2_unseal_trusted(struct tpm_chip *chip, - struct trusted_key_payload *payload, - struct trusted_key_options *options); ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value, const char *desc); diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index d103545..8bb34890 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -13,20 +13,6 @@ #include "tpm.h" #include -#include - -enum tpm2_object_attributes { - TPM2_OA_USER_WITH_AUTH = BIT(6), -}; - -enum tpm2_session_attributes { - TPM2_SA_CONTINUE_SESSION = BIT(0), -}; - -struct tpm2_hash { - unsigned int crypto_id; - unsigned int tpm_id; -}; static struct tpm2_hash tpm2_hash_map[] = { {HASH_ALGO_SHA1, TPM_ALG_SHA1}, @@ -376,299 +362,7 @@ void tpm2_flush_context(struct tpm_chip *chip, u32 handle) tpm_transmit_cmd(chip, &buf, 0, "flushing context"); tpm_buf_destroy(&buf); } - -/** - * tpm_buf_append_auth() - append TPMS_AUTH_COMMAND to the buffer. - * - * @buf: an allocated tpm_buf instance - * @session_handle: session handle - * @nonce: the session nonce, may be NULL if not used - * @nonce_len: the session nonce length, may be 0 if not used - * @attributes: the session attributes - * @hmac: the session HMAC or password, may be NULL if not used - * @hmac_len: the session HMAC or password length, maybe 0 if not used - */ -static void tpm2_buf_append_auth(struct tpm_buf *buf, u32 session_handle, - const u8 *nonce, u16 nonce_len, - u8 attributes, - const u8 *hmac, u16 hmac_len) -{ - tpm_buf_append_u32(buf, 9 + nonce_len + hmac_len); - tpm_buf_append_u32(buf, session_handle); - tpm_buf_append_u16(buf, nonce_len); - - if (nonce && nonce_len) - tpm_buf_append(buf, nonce, nonce_len); - - tpm_buf_append_u8(buf, attributes); - tpm_buf_append_u16(buf, hmac_len); - - if (hmac && hmac_len) - tpm_buf_append(buf, hmac, hmac_len); -} - -/** - * tpm2_seal_trusted() - seal the payload of a trusted key - * - * @chip: TPM chip to use - * @payload: the key data in clear and encrypted form - * @options: authentication values and other options - * - * Return: < 0 on error and 0 on success. - */ -int tpm2_seal_trusted(struct tpm_chip *chip, - struct trusted_key_payload *payload, - struct trusted_key_options *options) -{ - unsigned int blob_len; - struct tpm_buf buf; - u32 hash; - int i; - int rc; - - for (i = 0; i < ARRAY_SIZE(tpm2_hash_map); i++) { - if (options->hash == tpm2_hash_map[i].crypto_id) { - hash = tpm2_hash_map[i].tpm_id; - break; - } - } - - if (i == ARRAY_SIZE(tpm2_hash_map)) - return -EINVAL; - - rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE); - if (rc) - return rc; - - tpm_buf_append_u32(&buf, options->keyhandle); - tpm2_buf_append_auth(&buf, TPM2_RS_PW, - NULL /* nonce */, 0, - 0 /* session_attributes */, - options->keyauth /* hmac */, - TPM_DIGEST_SIZE); - - /* sensitive */ - tpm_buf_append_u16(&buf, 4 + TPM_DIGEST_SIZE + payload->key_len + 1); - - tpm_buf_append_u16(&buf, TPM_DIGEST_SIZE); - tpm_buf_append(&buf, options->blobauth, TPM_DIGEST_SIZE); - tpm_buf_append_u16(&buf, payload->key_len + 1); - tpm_buf_append(&buf, payload->key, payload->key_len); - tpm_buf_append_u8(&buf, payload->migratable); - - /* public */ - tpm_buf_append_u16(&buf, 14 + options->policydigest_len); - tpm_buf_append_u16(&buf, TPM_ALG_KEYEDHASH); - tpm_buf_append_u16(&buf, hash); - - /* policy */ - if (options->policydigest_len) { - tpm_buf_append_u32(&buf, 0); - tpm_buf_append_u16(&buf, options->policydigest_len); - tpm_buf_append(&buf, options->policydigest, - options->policydigest_len); - } else { - tpm_buf_append_u32(&buf, TPM2_OA_USER_WITH_AUTH); - tpm_buf_append_u16(&buf, 0); - } - - /* public parameters */ - tpm_buf_append_u16(&buf, TPM_ALG_NULL); - tpm_buf_append_u16(&buf, 0); - - /* outside info */ - tpm_buf_append_u16(&buf, 0); - - /* creation PCR */ - tpm_buf_append_u32(&buf, 0); - - if (buf.flags & TPM_BUF_OVERFLOW) { - rc = -E2BIG; - goto out; - } - - rc = tpm_transmit_cmd(chip, &buf, 4, "sealing data"); - if (rc) - goto out; - - blob_len = be32_to_cpup((__be32 *) &buf.data[TPM_HEADER_SIZE]); - if (blob_len > MAX_BLOB_SIZE) { - rc = -E2BIG; - goto out; - } - if (tpm_buf_length(&buf) < TPM_HEADER_SIZE + 4 + blob_len) { - rc = -EFAULT; - goto out; - } - - memcpy(payload->blob, &buf.data[TPM_HEADER_SIZE + 4], blob_len); - payload->blob_len = blob_len; - -out: - tpm_buf_destroy(&buf); - - if (rc > 0) { - if (tpm2_rc_value(rc) == TPM2_RC_HASH) - rc = -EINVAL; - else - rc = -EPERM; - } - - return rc; -} - -/** - * tpm2_load_cmd() - execute a TPM2_Load command - * - * @chip: TPM chip to use - * @payload: the key data in clear and encrypted form - * @options: authentication values and other options - * @blob_handle: returned blob handle - * - * Return: 0 on success. - * -E2BIG on wrong payload size. - * -EPERM on tpm error status. - * < 0 error from tpm_transmit_cmd. - */ -static int tpm2_load_cmd(struct tpm_chip *chip, - struct trusted_key_payload *payload, - struct trusted_key_options *options, - u32 *blob_handle) -{ - struct tpm_buf buf; - unsigned int private_len; - unsigned int public_len; - unsigned int blob_len; - int rc; - - private_len = be16_to_cpup((__be16 *) &payload->blob[0]); - if (private_len > (payload->blob_len - 2)) - return -E2BIG; - - public_len = be16_to_cpup((__be16 *) &payload->blob[2 + private_len]); - blob_len = private_len + public_len + 4; - if (blob_len > payload->blob_len) - return -E2BIG; - - rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD); - if (rc) - return rc; - - tpm_buf_append_u32(&buf, options->keyhandle); - tpm2_buf_append_auth(&buf, TPM2_RS_PW, - NULL /* nonce */, 0, - 0 /* session_attributes */, - options->keyauth /* hmac */, - TPM_DIGEST_SIZE); - - tpm_buf_append(&buf, payload->blob, blob_len); - - if (buf.flags & TPM_BUF_OVERFLOW) { - rc = -E2BIG; - goto out; - } - - rc = tpm_transmit_cmd(chip, &buf, 4, "loading blob"); - if (!rc) - *blob_handle = be32_to_cpup( - (__be32 *) &buf.data[TPM_HEADER_SIZE]); - -out: - tpm_buf_destroy(&buf); - - if (rc > 0) - rc = -EPERM; - - return rc; -} - -/** - * tpm2_unseal_cmd() - execute a TPM2_Unload command - * - * @chip: TPM chip to use - * @payload: the key data in clear and encrypted form - * @options: authentication values and other options - * @blob_handle: blob handle - * - * Return: 0 on success - * -EPERM on tpm error status - * < 0 error from tpm_transmit_cmd - */ -static int tpm2_unseal_cmd(struct tpm_chip *chip, - struct trusted_key_payload *payload, - struct trusted_key_options *options, - u32 blob_handle) -{ - struct tpm_buf buf; - u16 data_len; - u8 *data; - int rc; - - rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL); - if (rc) - return rc; - - tpm_buf_append_u32(&buf, blob_handle); - tpm2_buf_append_auth(&buf, - options->policyhandle ? - options->policyhandle : TPM2_RS_PW, - NULL /* nonce */, 0, - TPM2_SA_CONTINUE_SESSION, - options->blobauth /* hmac */, - TPM_DIGEST_SIZE); - - rc = tpm_transmit_cmd(chip, &buf, 6, "unsealing"); - if (rc > 0) - rc = -EPERM; - - if (!rc) { - data_len = be16_to_cpup( - (__be16 *) &buf.data[TPM_HEADER_SIZE + 4]); - if (data_len < MIN_KEY_SIZE || data_len > MAX_KEY_SIZE + 1) { - rc = -EFAULT; - goto out; - } - - if (tpm_buf_length(&buf) < TPM_HEADER_SIZE + 6 + data_len) { - rc = -EFAULT; - goto out; - } - data = &buf.data[TPM_HEADER_SIZE + 6]; - - memcpy(payload->key, data, data_len - 1); - payload->key_len = data_len - 1; - payload->migratable = data[data_len - 1]; - } - -out: - tpm_buf_destroy(&buf); - return rc; -} - -/** - * tpm2_unseal_trusted() - unseal the payload of a trusted key - * - * @chip: TPM chip to use - * @payload: the key data in clear and encrypted form - * @options: authentication values and other options - * - * Return: Same as with tpm_transmit_cmd. - */ -int tpm2_unseal_trusted(struct tpm_chip *chip, - struct trusted_key_payload *payload, - struct trusted_key_options *options) -{ - u32 blob_handle; - int rc; - - rc = tpm2_load_cmd(chip, payload, options, &blob_handle); - if (rc) - return rc; - - rc = tpm2_unseal_cmd(chip, payload, options, blob_handle); - tpm2_flush_context(chip, blob_handle); - return rc; -} +EXPORT_SYMBOL_GPL(tpm2_flush_context); struct tpm2_get_cap_out { u8 more_data; diff --git a/include/keys/trusted_tpm.h b/include/keys/trusted_tpm.h index 9bdf5f4..0d72106 100644 --- a/include/keys/trusted_tpm.h +++ b/include/keys/trusted_tpm.h @@ -37,6 +37,13 @@ int TSS_checkhmac1(unsigned char *buffer, int trusted_tpm_send(unsigned char *cmd, size_t buflen); int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce); +int tpm_seal_trusted(struct tpm_chip *chip, + struct trusted_key_payload *payload, + struct trusted_key_options *options); +int tpm_unseal_trusted(struct tpm_chip *chip, + struct trusted_key_payload *payload, + struct trusted_key_options *options); + #define TPM_DEBUG 0 #if TPM_DEBUG diff --git a/include/linux/tpm.h b/include/linux/tpm.h index 130c167..895179f 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -294,6 +294,19 @@ struct tpm_buf { u8 *data; }; +enum tpm2_object_attributes { + TPM2_OA_USER_WITH_AUTH = BIT(6), +}; + +enum tpm2_session_attributes { + TPM2_SA_CONTINUE_SESSION = BIT(0), +}; + +struct tpm2_hash { + unsigned int crypto_id; + unsigned int tpm_id; +}; + static inline void tpm_buf_reset(struct tpm_buf *buf, u16 tag, u32 ordinal) { struct tpm_header *head = (struct tpm_header *)buf->data; @@ -375,6 +388,11 @@ static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value) tpm_buf_append(buf, (u8 *) &value2, 4); } +static inline u32 tpm2_rc_value(u32 rc) +{ + return (rc & BIT(7)) ? rc & 0xff : rc; +} + #if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE) extern int tpm_is_tpm2(struct tpm_chip *chip); @@ -384,13 +402,12 @@ extern int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, struct tpm_digest *digests); extern int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen); extern int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max); -extern int tpm_seal_trusted(struct tpm_chip *chip, - struct trusted_key_payload *payload, - struct trusted_key_options *options); -extern int tpm_unseal_trusted(struct tpm_chip *chip, - struct trusted_key_payload *payload, - struct trusted_key_options *options); extern struct tpm_chip *tpm_default_chip(void); +extern struct tpm_chip *tpm_find_get_ops(struct tpm_chip *chip); +extern void tpm_put_ops(struct tpm_chip *chip); +extern ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_buf *buf, + size_t min_rsp_body_length, const char *desc); +extern void tpm2_flush_context(struct tpm_chip *chip, u32 handle); #else static inline int tpm_is_tpm2(struct tpm_chip *chip) { @@ -418,21 +435,30 @@ static inline int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max) return -ENODEV; } -static inline int tpm_seal_trusted(struct tpm_chip *chip, - struct trusted_key_payload *payload, - struct trusted_key_options *options) +static inline struct tpm_chip *tpm_default_chip(void) { - return -ENODEV; + return NULL; } -static inline int tpm_unseal_trusted(struct tpm_chip *chip, - struct trusted_key_payload *payload, - struct trusted_key_options *options) + +static inline struct tpm_chip *tpm_find_get_ops(struct tpm_chip *chip) +{ + return NULL; +} + +static inline void tpm_put_ops(struct tpm_chip *chip) +{ +} + +static inline ssize_t tpm_transmit_cmd(struct tpm_chip *chip, + struct tpm_buf *buf, + size_t min_rsp_body_length, + const char *desc) { return -ENODEV; } -static inline struct tpm_chip *tpm_default_chip(void) + +static inline void tpm2_flush_context(struct tpm_chip *chip, u32 handle) { - return NULL; } #endif #endif diff --git a/security/keys/trusted-keys/Makefile b/security/keys/trusted-keys/Makefile index 4e8963a..fb42e94 100644 --- a/security/keys/trusted-keys/Makefile +++ b/security/keys/trusted-keys/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_TRUSTED_KEYS) += trusted.o trusted-y += trusted-tpm.o +trusted-y += trusted-tpm2.o diff --git a/security/keys/trusted-keys/trusted-tpm2.c b/security/keys/trusted-keys/trusted-tpm2.c new file mode 100644 index 0000000..98892ed7 --- /dev/null +++ b/security/keys/trusted-keys/trusted-tpm2.c @@ -0,0 +1,378 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2004 IBM Corporation + * Copyright (C) 2014 Intel Corporation + * + * Authors: + * Leendert van Doorn + * Dave Safford + * Reiner Sailer + * Kylene Hall + * + * Maintained by: + * + * Trusted Keys code for TCG/TCPA TPM2 (trusted platform module). + */ + +#include +#include +#include +#include + +#include +#include + +static struct tpm2_hash tpm2_hash_map[] = { + {HASH_ALGO_SHA1, TPM_ALG_SHA1}, + {HASH_ALGO_SHA256, TPM_ALG_SHA256}, + {HASH_ALGO_SHA384, TPM_ALG_SHA384}, + {HASH_ALGO_SHA512, TPM_ALG_SHA512}, + {HASH_ALGO_SM3_256, TPM_ALG_SM3_256}, +}; + +/** + * tpm_buf_append_auth() - append TPMS_AUTH_COMMAND to the buffer. + * + * @buf: an allocated tpm_buf instance + * @session_handle: session handle + * @nonce: the session nonce, may be NULL if not used + * @nonce_len: the session nonce length, may be 0 if not used + * @attributes: the session attributes + * @hmac: the session HMAC or password, may be NULL if not used + * @hmac_len: the session HMAC or password length, maybe 0 if not used + */ +static void tpm2_buf_append_auth(struct tpm_buf *buf, u32 session_handle, + const u8 *nonce, u16 nonce_len, + u8 attributes, + const u8 *hmac, u16 hmac_len) +{ + tpm_buf_append_u32(buf, 9 + nonce_len + hmac_len); + tpm_buf_append_u32(buf, session_handle); + tpm_buf_append_u16(buf, nonce_len); + + if (nonce && nonce_len) + tpm_buf_append(buf, nonce, nonce_len); + + tpm_buf_append_u8(buf, attributes); + tpm_buf_append_u16(buf, hmac_len); + + if (hmac && hmac_len) + tpm_buf_append(buf, hmac, hmac_len); +} + +/** + * tpm2_seal_trusted() - seal the payload of a trusted key + * + * @chip: TPM chip to use + * @payload: the key data in clear and encrypted form + * @options: authentication values and other options + * + * Return: < 0 on error and 0 on success. + */ +int tpm2_seal_trusted(struct tpm_chip *chip, + struct trusted_key_payload *payload, + struct trusted_key_options *options) +{ + unsigned int blob_len; + struct tpm_buf buf; + u32 hash; + int i; + int rc; + + for (i = 0; i < ARRAY_SIZE(tpm2_hash_map); i++) { + if (options->hash == tpm2_hash_map[i].crypto_id) { + hash = tpm2_hash_map[i].tpm_id; + break; + } + } + + if (i == ARRAY_SIZE(tpm2_hash_map)) + return -EINVAL; + + rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE); + if (rc) + return rc; + + tpm_buf_append_u32(&buf, options->keyhandle); + tpm2_buf_append_auth(&buf, TPM2_RS_PW, + NULL /* nonce */, 0, + 0 /* session_attributes */, + options->keyauth /* hmac */, + TPM_DIGEST_SIZE); + + /* sensitive */ + tpm_buf_append_u16(&buf, 4 + TPM_DIGEST_SIZE + payload->key_len + 1); + + tpm_buf_append_u16(&buf, TPM_DIGEST_SIZE); + tpm_buf_append(&buf, options->blobauth, TPM_DIGEST_SIZE); + tpm_buf_append_u16(&buf, payload->key_len + 1); + tpm_buf_append(&buf, payload->key, payload->key_len); + tpm_buf_append_u8(&buf, payload->migratable); + + /* public */ + tpm_buf_append_u16(&buf, 14 + options->policydigest_len); + tpm_buf_append_u16(&buf, TPM_ALG_KEYEDHASH); + tpm_buf_append_u16(&buf, hash); + + /* policy */ + if (options->policydigest_len) { + tpm_buf_append_u32(&buf, 0); + tpm_buf_append_u16(&buf, options->policydigest_len); + tpm_buf_append(&buf, options->policydigest, + options->policydigest_len); + } else { + tpm_buf_append_u32(&buf, TPM2_OA_USER_WITH_AUTH); + tpm_buf_append_u16(&buf, 0); + } + + /* public parameters */ + tpm_buf_append_u16(&buf, TPM_ALG_NULL); + tpm_buf_append_u16(&buf, 0); + + /* outside info */ + tpm_buf_append_u16(&buf, 0); + + /* creation PCR */ + tpm_buf_append_u32(&buf, 0); + + if (buf.flags & TPM_BUF_OVERFLOW) { + rc = -E2BIG; + goto out; + } + + rc = tpm_transmit_cmd(chip, &buf, 4, "sealing data"); + if (rc) + goto out; + + blob_len = be32_to_cpup((__be32 *) &buf.data[TPM_HEADER_SIZE]); + if (blob_len > MAX_BLOB_SIZE) { + rc = -E2BIG; + goto out; + } + if (tpm_buf_length(&buf) < TPM_HEADER_SIZE + 4 + blob_len) { + rc = -EFAULT; + goto out; + } + + memcpy(payload->blob, &buf.data[TPM_HEADER_SIZE + 4], blob_len); + payload->blob_len = blob_len; + +out: + tpm_buf_destroy(&buf); + + if (rc > 0) { + if (tpm2_rc_value(rc) == TPM2_RC_HASH) + rc = -EINVAL; + else + rc = -EPERM; + } + + return rc; +} + +/** + * tpm_seal_trusted() - seal a trusted key payload + * @chip: a &struct tpm_chip instance, %NULL for the default chip + * @options: authentication values and other options + * @payload: the key data in clear and encrypted form + * + * Note: only TPM 2.0 chip are supported. TPM 1.x implementation is located in + * the keyring subsystem. + * + * Return: same as with tpm_transmit_cmd() + */ +int tpm_seal_trusted(struct tpm_chip *chip, struct trusted_key_payload *payload, + struct trusted_key_options *options) +{ + int rc; + + chip = tpm_find_get_ops(chip); + if (!chip || !(chip->flags & TPM_CHIP_FLAG_TPM2)) + return -ENODEV; + + rc = tpm2_seal_trusted(chip, payload, options); + + tpm_put_ops(chip); + return rc; +} + +/** + * tpm2_load_cmd() - execute a TPM2_Load command + * + * @chip: TPM chip to use + * @payload: the key data in clear and encrypted form + * @options: authentication values and other options + * @blob_handle: returned blob handle + * + * Return: 0 on success. + * -E2BIG on wrong payload size. + * -EPERM on tpm error status. + * < 0 error from tpm_transmit_cmd. + */ +static int tpm2_load_cmd(struct tpm_chip *chip, + struct trusted_key_payload *payload, + struct trusted_key_options *options, + u32 *blob_handle) +{ + struct tpm_buf buf; + unsigned int private_len; + unsigned int public_len; + unsigned int blob_len; + int rc; + + private_len = be16_to_cpup((__be16 *) &payload->blob[0]); + if (private_len > (payload->blob_len - 2)) + return -E2BIG; + + public_len = be16_to_cpup((__be16 *) &payload->blob[2 + private_len]); + blob_len = private_len + public_len + 4; + if (blob_len > payload->blob_len) + return -E2BIG; + + rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD); + if (rc) + return rc; + + tpm_buf_append_u32(&buf, options->keyhandle); + tpm2_buf_append_auth(&buf, TPM2_RS_PW, + NULL /* nonce */, 0, + 0 /* session_attributes */, + options->keyauth /* hmac */, + TPM_DIGEST_SIZE); + + tpm_buf_append(&buf, payload->blob, blob_len); + + if (buf.flags & TPM_BUF_OVERFLOW) { + rc = -E2BIG; + goto out; + } + + rc = tpm_transmit_cmd(chip, &buf, 4, "loading blob"); + if (!rc) + *blob_handle = be32_to_cpup( + (__be32 *) &buf.data[TPM_HEADER_SIZE]); + +out: + tpm_buf_destroy(&buf); + + if (rc > 0) + rc = -EPERM; + + return rc; +} + +/** + * tpm2_unseal_cmd() - execute a TPM2_Unload command + * + * @chip: TPM chip to use + * @payload: the key data in clear and encrypted form + * @options: authentication values and other options + * @blob_handle: blob handle + * + * Return: 0 on success + * -EPERM on tpm error status + * < 0 error from tpm_transmit_cmd + */ +static int tpm2_unseal_cmd(struct tpm_chip *chip, + struct trusted_key_payload *payload, + struct trusted_key_options *options, + u32 blob_handle) +{ + struct tpm_buf buf; + u16 data_len; + u8 *data; + int rc; + + rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL); + if (rc) + return rc; + + tpm_buf_append_u32(&buf, blob_handle); + tpm2_buf_append_auth(&buf, + options->policyhandle ? + options->policyhandle : TPM2_RS_PW, + NULL /* nonce */, 0, + TPM2_SA_CONTINUE_SESSION, + options->blobauth /* hmac */, + TPM_DIGEST_SIZE); + + rc = tpm_transmit_cmd(chip, &buf, 6, "unsealing"); + if (rc > 0) + rc = -EPERM; + + if (!rc) { + data_len = be16_to_cpup( + (__be16 *) &buf.data[TPM_HEADER_SIZE + 4]); + if (data_len < MIN_KEY_SIZE || data_len > MAX_KEY_SIZE + 1) { + rc = -EFAULT; + goto out; + } + + if (tpm_buf_length(&buf) < TPM_HEADER_SIZE + 6 + data_len) { + rc = -EFAULT; + goto out; + } + data = &buf.data[TPM_HEADER_SIZE + 6]; + + memcpy(payload->key, data, data_len - 1); + payload->key_len = data_len - 1; + payload->migratable = data[data_len - 1]; + } + +out: + tpm_buf_destroy(&buf); + return rc; +} + +/** + * tpm2_unseal_trusted() - unseal the payload of a trusted key + * + * @chip: TPM chip to use + * @payload: the key data in clear and encrypted form + * @options: authentication values and other options + * + * Return: Same as with tpm_transmit_cmd. + */ +int tpm2_unseal_trusted(struct tpm_chip *chip, + struct trusted_key_payload *payload, + struct trusted_key_options *options) +{ + u32 blob_handle; + int rc; + + rc = tpm2_load_cmd(chip, payload, options, &blob_handle); + if (rc) + return rc; + + rc = tpm2_unseal_cmd(chip, payload, options, blob_handle); + tpm2_flush_context(chip, blob_handle); + return rc; +} + +/** + * tpm_unseal_trusted() - unseal a trusted key + * @chip: a &struct tpm_chip instance, %NULL for the default chip + * @options: authentication values and other options + * @payload: the key data in clear and encrypted form + * + * Note: only TPM 2.0 chip are supported. TPM 1.x implementation is located in + * the keyring subsystem. + * + * Return: same as with tpm_transmit_cmd() + */ +int tpm_unseal_trusted(struct tpm_chip *chip, + struct trusted_key_payload *payload, + struct trusted_key_options *options) +{ + int rc; + + chip = tpm_find_get_ops(chip); + if (!chip || !(chip->flags & TPM_CHIP_FLAG_TPM2)) + return -ENODEV; + + rc = tpm2_unseal_trusted(chip, payload, options); + + tpm_put_ops(chip); + + return rc; +} From patchwork Tue Aug 13 07:53:04 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sumit Garg X-Patchwork-Id: 11091435 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id ECCC0112C for ; Tue, 13 Aug 2019 07:54:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E0BAA285C7 for ; Tue, 13 Aug 2019 07:54:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D4F6B285EF; Tue, 13 Aug 2019 07:54:54 +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.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,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 53BBD285C7 for ; Tue, 13 Aug 2019 07:54:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727984AbfHMHyw (ORCPT ); Tue, 13 Aug 2019 03:54:52 -0400 Received: from mail-pg1-f194.google.com ([209.85.215.194]:46917 "EHLO mail-pg1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727959AbfHMHyw (ORCPT ); Tue, 13 Aug 2019 03:54:52 -0400 Received: by mail-pg1-f194.google.com with SMTP id w3so13625889pgt.13 for ; Tue, 13 Aug 2019 00:54:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=S2MwqLo3dNEfa1tBMLsf6483pf8QLWvxy34MPrwvEWY=; b=eYY6xUelFXOIUGrhyCvt1Vq6GW1mYwo5e/85C8M51ARIOnKtvvib3oqLMGmh04relY gsVQOJBXuuq0/x6brgPwlvJIGt76+g+nZkKxD+Rn3PXxyNqOwBhHA8aiHPOI9Lhk2vCi zavaNx/sGmuB14o4UEPGijMaMfVxp07MI2IL6f45dJ0z1yeiutvD2R8a5qLoYRvU6Ikd UROYFhN/cV13Lfu8jLvd2gLinS1BdbuZjkq9OB4FpY2s0rCHpBbGuZyotWNYA0i6lvYx VPyxhpfxuarSj4DY/Z2kOPD8e3pATM6Adqz9nrTDNekhmU1fuFhy6nvsntbeJ6sYEuyF lkrw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=S2MwqLo3dNEfa1tBMLsf6483pf8QLWvxy34MPrwvEWY=; b=ooLgSJPP7GsIwTw42Jc1kFXwn6uJQKHGe4DyzDwk6Nm0pm5x/lPEbW1RS318hRKwbo 7LvuCJ+eoeWnJwpJra4ycApUYOx86BK7Bj32HOzfLCIump3peBlnTGAfmcWdfxBYnhcN Fk+APPpfA3V6lhmcFNTghSa0+XdYeLJN4ZnGKbanm2hRJp7GCpXyKjSm7vQZGD0BocxR tTdFsIdnXPBPXaBehLHlHe79mSjev926t0j+KMklV+uC0XqGxngCVKx5SSznRbRRZI/f MLwHcNNCye+tXv36V10y5zK7lTkEDXECklOM4Hs074F4I+oFddw14c2zFM1zwQVdHXF2 JU7g== X-Gm-Message-State: APjAAAUyakli0/GMuGVOHcXEF7EK4iJLfwxwga/KtDld7XAmO+ul0LEf ozZIHS8yJw2XyQ6qn6vdvyaW4g== X-Google-Smtp-Source: APXvYqwQnQ1fsocwCgTK2SmQQm/WMSCvzFm5bNUDCOvbf1nm+f13m88m+z0G0fE1qICFilQ4X2D7DQ== X-Received: by 2002:a63:8dc9:: with SMTP id z192mr32795439pgd.151.1565682891600; Tue, 13 Aug 2019 00:54:51 -0700 (PDT) Received: from localhost.localdomain ([45.114.72.100]) by smtp.gmail.com with ESMTPSA id l25sm131462563pff.143.2019.08.13.00.54.38 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 13 Aug 2019 00:54:50 -0700 (PDT) From: Sumit Garg To: keyrings@vger.kernel.org, linux-integrity@vger.kernel.org, linux-crypto@vger.kernel.org, linux-security-module@vger.kernel.org Cc: dhowells@redhat.com, herbert@gondor.apana.org.au, davem@davemloft.net, peterhuewe@gmx.de, jgg@ziepe.ca, jejb@linux.ibm.com, jarkko.sakkinen@linux.intel.com, arnd@arndb.de, gregkh@linuxfoundation.org, zohar@linux.ibm.com, jmorris@namei.org, serge@hallyn.com, casey@schaufler-ca.com, ard.biesheuvel@linaro.org, daniel.thompson@linaro.org, linux-kernel@vger.kernel.org, tee-dev@lists.linaro.org, Sumit Garg Subject: [RFC/RFT v4 5/5] KEYS: trusted: Add generic trusted keys framework Date: Tue, 13 Aug 2019 13:23:04 +0530 Message-Id: <1565682784-10234-6-git-send-email-sumit.garg@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1565682784-10234-1-git-send-email-sumit.garg@linaro.org> References: <1565682784-10234-1-git-send-email-sumit.garg@linaro.org> Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP Current trusted keys framework is tightly coupled to use TPM device as an underlying implementation which makes it difficult for implementations like Trusted Execution Environment (TEE) etc. to provide trusked keys support in case platform doesn't posses a TPM device. So this patch tries to add generic trusted keys framework where underlying implemtations like TPM, TEE etc. could be easily plugged-in. Suggested-by: Jarkko Sakkinen Signed-off-by: Sumit Garg --- include/keys/trusted-type.h | 45 ++++ include/keys/trusted_tpm.h | 15 -- security/keys/trusted-keys/Makefile | 1 + security/keys/trusted-keys/trusted-common.c | 343 +++++++++++++++++++++++++++ security/keys/trusted-keys/trusted-tpm.c | 345 +++++----------------------- 5 files changed, 447 insertions(+), 302 deletions(-) create mode 100644 security/keys/trusted-keys/trusted-common.c diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h index a94c03a..5559010 100644 --- a/include/keys/trusted-type.h +++ b/include/keys/trusted-type.h @@ -40,6 +40,51 @@ struct trusted_key_options { uint32_t policyhandle; }; +struct trusted_key_ops { + /* + * flag to indicate if trusted key implementation supports migration + * or not. + */ + unsigned char migratable; + + /* trusted key init */ + int (*init)(void); + + /* seal a trusted key */ + int (*seal)(struct trusted_key_payload *p, char *datablob); + + /* unseal a trusted key */ + int (*unseal)(struct trusted_key_payload *p, char *datablob); + + /* get random trusted key */ + int (*get_random)(unsigned char *key, size_t key_len); + + /* trusted key cleanup */ + void (*cleanup)(void); +}; + extern struct key_type key_type_trusted; +#if defined(CONFIG_TCG_TPM) +extern struct trusted_key_ops tpm_trusted_key_ops; +#endif + +#define TRUSTED_DEBUG 0 + +#if TRUSTED_DEBUG +static inline void dump_payload(struct trusted_key_payload *p) +{ + pr_info("trusted_key: key_len %d\n", p->key_len); + print_hex_dump(KERN_INFO, "key ", DUMP_PREFIX_NONE, + 16, 1, p->key, p->key_len, 0); + pr_info("trusted_key: bloblen %d\n", p->blob_len); + print_hex_dump(KERN_INFO, "blob ", DUMP_PREFIX_NONE, + 16, 1, p->blob, p->blob_len, 0); + pr_info("trusted_key: migratable %d\n", p->migratable); +} +#else +static inline void dump_payload(struct trusted_key_payload *p) +{ +} +#endif #endif /* _KEYS_TRUSTED_TYPE_H */ diff --git a/include/keys/trusted_tpm.h b/include/keys/trusted_tpm.h index 0d72106..7b59344 100644 --- a/include/keys/trusted_tpm.h +++ b/include/keys/trusted_tpm.h @@ -57,17 +57,6 @@ static inline void dump_options(struct trusted_key_options *o) 16, 1, o->pcrinfo, o->pcrinfo_len, 0); } -static inline void dump_payload(struct trusted_key_payload *p) -{ - pr_info("trusted_key: key_len %d\n", p->key_len); - print_hex_dump(KERN_INFO, "key ", DUMP_PREFIX_NONE, - 16, 1, p->key, p->key_len, 0); - pr_info("trusted_key: bloblen %d\n", p->blob_len); - print_hex_dump(KERN_INFO, "blob ", DUMP_PREFIX_NONE, - 16, 1, p->blob, p->blob_len, 0); - pr_info("trusted_key: migratable %d\n", p->migratable); -} - static inline void dump_sess(struct osapsess *s) { print_hex_dump(KERN_INFO, "trusted-key: handle ", DUMP_PREFIX_NONE, @@ -93,10 +82,6 @@ static inline void dump_options(struct trusted_key_options *o) { } -static inline void dump_payload(struct trusted_key_payload *p) -{ -} - static inline void dump_sess(struct osapsess *s) { } diff --git a/security/keys/trusted-keys/Makefile b/security/keys/trusted-keys/Makefile index fb42e94..9a4f721 100644 --- a/security/keys/trusted-keys/Makefile +++ b/security/keys/trusted-keys/Makefile @@ -4,5 +4,6 @@ # obj-$(CONFIG_TRUSTED_KEYS) += trusted.o +trusted-y += trusted-common.o trusted-y += trusted-tpm.o trusted-y += trusted-tpm2.o diff --git a/security/keys/trusted-keys/trusted-common.c b/security/keys/trusted-keys/trusted-common.c new file mode 100644 index 0000000..8f00fde --- /dev/null +++ b/security/keys/trusted-keys/trusted-common.c @@ -0,0 +1,343 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2010 IBM Corporation + * Copyright (c) 2019, Linaro Limited + * + * Author: + * David Safford + * Added generic trusted key framework: Sumit Garg + * + * See Documentation/security/keys/trusted-encrypted.rst + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct trusted_key_ops *available_tk_ops[] = { +#if defined(CONFIG_TCG_TPM) + &tpm_trusted_key_ops, +#endif +}; +static struct trusted_key_ops *tk_ops; + +enum { + Opt_err, + Opt_new, Opt_load, Opt_update, +}; + +static const match_table_t key_tokens = { + {Opt_new, "new"}, + {Opt_load, "load"}, + {Opt_update, "update"}, + {Opt_err, NULL} +}; + +/* + * datablob_parse - parse the keyctl data and fill in the + * payload structure + * + * On success returns 0, otherwise -EINVAL. + */ +static int datablob_parse(char *datablob, struct trusted_key_payload *p) +{ + substring_t args[MAX_OPT_ARGS]; + long keylen; + int ret = -EINVAL; + int key_cmd; + char *c; + + /* main command */ + c = strsep(&datablob, " \t"); + if (!c) + return -EINVAL; + key_cmd = match_token(c, key_tokens, args); + switch (key_cmd) { + case Opt_new: + /* first argument is key size */ + c = strsep(&datablob, " \t"); + if (!c) + return -EINVAL; + ret = kstrtol(c, 10, &keylen); + if (ret < 0 || keylen < MIN_KEY_SIZE || keylen > MAX_KEY_SIZE) + return -EINVAL; + p->key_len = keylen; + ret = Opt_new; + break; + case Opt_load: + /* first argument is sealed blob */ + c = strsep(&datablob, " \t"); + if (!c) + return -EINVAL; + p->blob_len = strlen(c) / 2; + if (p->blob_len > MAX_BLOB_SIZE) + return -EINVAL; + ret = hex2bin(p->blob, c, p->blob_len); + if (ret < 0) + return -EINVAL; + ret = Opt_load; + break; + case Opt_update: + ret = Opt_update; + break; + case Opt_err: + return -EINVAL; + } + return ret; +} + +static struct trusted_key_payload *trusted_payload_alloc(struct key *key) +{ + struct trusted_key_payload *p = NULL; + int ret; + + ret = key_payload_reserve(key, sizeof(*p)); + if (ret < 0) + return p; + p = kzalloc(sizeof(*p), GFP_KERNEL); + + p->migratable = tk_ops->migratable; + + return p; +} + +/* + * trusted_instantiate - create a new trusted key + * + * Unseal an existing trusted blob or, for a new key, get a + * random key, then seal and create a trusted key-type key, + * adding it to the specified keyring. + * + * On success, return 0. Otherwise return errno. + */ +static int trusted_instantiate(struct key *key, + struct key_preparsed_payload *prep) +{ + struct trusted_key_payload *payload = NULL; + size_t datalen = prep->datalen; + char *datablob; + int ret = 0; + int key_cmd; + size_t key_len; + + if (datalen <= 0 || datalen > 32767 || !prep->data) + return -EINVAL; + + datablob = kmalloc(datalen + 1, GFP_KERNEL); + if (!datablob) + return -ENOMEM; + memcpy(datablob, prep->data, datalen); + datablob[datalen] = '\0'; + + payload = trusted_payload_alloc(key); + if (!payload) { + ret = -ENOMEM; + goto out; + } + + key_cmd = datablob_parse(datablob, payload); + if (key_cmd < 0) { + ret = key_cmd; + goto out; + } + + dump_payload(payload); + + switch (key_cmd) { + case Opt_load: + ret = tk_ops->unseal(payload, datablob); + dump_payload(payload); + if (ret < 0) + pr_info("trusted_key: key_unseal failed (%d)\n", ret); + break; + case Opt_new: + key_len = payload->key_len; + ret = tk_ops->get_random(payload->key, key_len); + if (ret != key_len) { + pr_info("trusted_key: key_create failed (%d)\n", ret); + goto out; + } + + ret = tk_ops->seal(payload, datablob); + if (ret < 0) + pr_info("trusted_key: key_seal failed (%d)\n", ret); + break; + default: + ret = -EINVAL; + } +out: + kzfree(datablob); + if (!ret) + rcu_assign_keypointer(key, payload); + else + kzfree(payload); + return ret; +} + +static void trusted_rcu_free(struct rcu_head *rcu) +{ + struct trusted_key_payload *p; + + p = container_of(rcu, struct trusted_key_payload, rcu); + kzfree(p); +} + +/* + * trusted_update - reseal an existing key with new PCR values + */ +static int trusted_update(struct key *key, struct key_preparsed_payload *prep) +{ + struct trusted_key_payload *p; + struct trusted_key_payload *new_p; + size_t datalen = prep->datalen; + char *datablob; + int ret = 0; + + if (key_is_negative(key)) + return -ENOKEY; + p = key->payload.data[0]; + if (!p->migratable) + return -EPERM; + if (datalen <= 0 || datalen > 32767 || !prep->data) + return -EINVAL; + + datablob = kmalloc(datalen + 1, GFP_KERNEL); + if (!datablob) + return -ENOMEM; + + new_p = trusted_payload_alloc(key); + if (!new_p) { + ret = -ENOMEM; + goto out; + } + + memcpy(datablob, prep->data, datalen); + datablob[datalen] = '\0'; + ret = datablob_parse(datablob, new_p); + if (ret != Opt_update) { + ret = -EINVAL; + kzfree(new_p); + goto out; + } + + /* copy old key values, and reseal with new pcrs */ + new_p->migratable = p->migratable; + new_p->key_len = p->key_len; + memcpy(new_p->key, p->key, p->key_len); + dump_payload(p); + dump_payload(new_p); + + ret = tk_ops->seal(new_p, datablob); + if (ret < 0) { + pr_info("trusted_key: key_seal failed (%d)\n", ret); + kzfree(new_p); + goto out; + } + + rcu_assign_keypointer(key, new_p); + call_rcu(&p->rcu, trusted_rcu_free); +out: + kzfree(datablob); + return ret; +} + +/* + * trusted_read - copy the sealed blob data to userspace in hex. + * On success, return to userspace the trusted key datablob size. + */ +static long trusted_read(const struct key *key, char __user *buffer, + size_t buflen) +{ + const struct trusted_key_payload *p; + char *ascii_buf; + char *bufp; + int i; + + p = dereference_key_locked(key); + if (!p) + return -EINVAL; + + if (buffer && buflen >= 2 * p->blob_len) { + ascii_buf = kmalloc_array(2, p->blob_len, GFP_KERNEL); + if (!ascii_buf) + return -ENOMEM; + + bufp = ascii_buf; + for (i = 0; i < p->blob_len; i++) + bufp = hex_byte_pack(bufp, p->blob[i]); + if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) { + kzfree(ascii_buf); + return -EFAULT; + } + kzfree(ascii_buf); + } + return 2 * p->blob_len; +} + +/* + * trusted_destroy - clear and free the key's payload + */ +static void trusted_destroy(struct key *key) +{ + kzfree(key->payload.data[0]); +} + +struct key_type key_type_trusted = { + .name = "trusted", + .instantiate = trusted_instantiate, + .update = trusted_update, + .destroy = trusted_destroy, + .describe = user_describe, + .read = trusted_read, +}; +EXPORT_SYMBOL_GPL(key_type_trusted); + +static int __init init_trusted(void) +{ + int i, ret = 0; + + for (i = 0; i < sizeof(available_tk_ops); i++) { + tk_ops = available_tk_ops[i]; + + if (!(tk_ops && tk_ops->init && tk_ops->seal && + tk_ops->unseal && tk_ops->get_random)) + continue; + + ret = tk_ops->init(); + if (ret) { + if (tk_ops->cleanup) + tk_ops->cleanup(); + } else { + break; + } + } + + /* + * encrypted_keys.ko depends on successful load of this module even if + * trusted key implementation is not found. + */ + if (ret == -ENODEV) + return 0; + + return ret; +} + +static void __exit cleanup_trusted(void) +{ + if (tk_ops->cleanup) + tk_ops->cleanup(); +} + +late_initcall(init_trusted); +module_exit(cleanup_trusted); + +MODULE_LICENSE("GPL"); diff --git a/security/keys/trusted-keys/trusted-tpm.c b/security/keys/trusted-keys/trusted-tpm.c index 66687e7..dab7c32 100644 --- a/security/keys/trusted-keys/trusted-tpm.c +++ b/security/keys/trusted-keys/trusted-tpm.c @@ -1,29 +1,26 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2010 IBM Corporation + * Copyright (c) 2019, Linaro Limited * * Author: * David Safford + * Switch to generic trusted key framework: Sumit Garg * * See Documentation/security/keys/trusted-encrypted.rst */ #include -#include -#include #include #include #include #include #include -#include #include #include -#include #include #include #include -#include #include #include @@ -705,7 +702,6 @@ static int key_unseal(struct trusted_key_payload *p, enum { Opt_err, - Opt_new, Opt_load, Opt_update, Opt_keyhandle, Opt_keyauth, Opt_blobauth, Opt_pcrinfo, Opt_pcrlock, Opt_migratable, Opt_hash, @@ -714,9 +710,6 @@ enum { }; static const match_table_t key_tokens = { - {Opt_new, "new"}, - {Opt_load, "load"}, - {Opt_update, "update"}, {Opt_keyhandle, "keyhandle=%s"}, {Opt_keyauth, "keyauth=%s"}, {Opt_blobauth, "blobauth=%s"}, @@ -843,71 +836,6 @@ static int getoptions(char *c, struct trusted_key_payload *pay, return 0; } -/* - * datablob_parse - parse the keyctl data and fill in the - * payload and options structures - * - * On success returns 0, otherwise -EINVAL. - */ -static int datablob_parse(char *datablob, struct trusted_key_payload *p, - struct trusted_key_options *o) -{ - substring_t args[MAX_OPT_ARGS]; - long keylen; - int ret = -EINVAL; - int key_cmd; - char *c; - - /* main command */ - c = strsep(&datablob, " \t"); - if (!c) - return -EINVAL; - key_cmd = match_token(c, key_tokens, args); - switch (key_cmd) { - case Opt_new: - /* first argument is key size */ - c = strsep(&datablob, " \t"); - if (!c) - return -EINVAL; - ret = kstrtol(c, 10, &keylen); - if (ret < 0 || keylen < MIN_KEY_SIZE || keylen > MAX_KEY_SIZE) - return -EINVAL; - p->key_len = keylen; - ret = getoptions(datablob, p, o); - if (ret < 0) - return ret; - ret = Opt_new; - break; - case Opt_load: - /* first argument is sealed blob */ - c = strsep(&datablob, " \t"); - if (!c) - return -EINVAL; - p->blob_len = strlen(c) / 2; - if (p->blob_len > MAX_BLOB_SIZE) - return -EINVAL; - ret = hex2bin(p->blob, c, p->blob_len); - if (ret < 0) - return -EINVAL; - ret = getoptions(datablob, p, o); - if (ret < 0) - return ret; - ret = Opt_load; - break; - case Opt_update: - /* all arguments are options */ - ret = getoptions(datablob, p, o); - if (ret < 0) - return ret; - ret = Opt_update; - break; - case Opt_err: - return -EINVAL; - break; - } - return ret; -} - static struct trusted_key_options *trusted_options_alloc(void) { struct trusted_key_options *options; @@ -928,258 +856,99 @@ static struct trusted_key_options *trusted_options_alloc(void) return options; } -static struct trusted_key_payload *trusted_payload_alloc(struct key *key) +static int tpm_tk_seal(struct trusted_key_payload *p, char *datablob) { - struct trusted_key_payload *p = NULL; - int ret; - - ret = key_payload_reserve(key, sizeof *p); - if (ret < 0) - return p; - p = kzalloc(sizeof *p, GFP_KERNEL); - if (p) - p->migratable = 1; /* migratable by default */ - return p; -} - -/* - * trusted_instantiate - create a new trusted key - * - * Unseal an existing trusted blob or, for a new key, get a - * random key, then seal and create a trusted key-type key, - * adding it to the specified keyring. - * - * On success, return 0. Otherwise return errno. - */ -static int trusted_instantiate(struct key *key, - struct key_preparsed_payload *prep) -{ - struct trusted_key_payload *payload = NULL; struct trusted_key_options *options = NULL; - size_t datalen = prep->datalen; - char *datablob; int ret = 0; - int key_cmd; - size_t key_len; int tpm2; tpm2 = tpm_is_tpm2(chip); if (tpm2 < 0) return tpm2; - if (datalen <= 0 || datalen > 32767 || !prep->data) - return -EINVAL; - - datablob = kmalloc(datalen + 1, GFP_KERNEL); - if (!datablob) - return -ENOMEM; - memcpy(datablob, prep->data, datalen); - datablob[datalen] = '\0'; - options = trusted_options_alloc(); - if (!options) { - ret = -ENOMEM; - goto out; - } - payload = trusted_payload_alloc(key); - if (!payload) { - ret = -ENOMEM; - goto out; - } + if (!options) + return -ENOMEM; - key_cmd = datablob_parse(datablob, payload, options); - if (key_cmd < 0) { - ret = key_cmd; + ret = getoptions(datablob, p, options); + if (ret < 0) goto out; - } + dump_options(options); if (!options->keyhandle) { ret = -EINVAL; goto out; } - dump_payload(payload); - dump_options(options); + if (tpm2) + ret = tpm_seal_trusted(chip, p, options); + else + ret = key_seal(p, options); + if (ret < 0) { + pr_info("tpm_trusted_key: key_seal failed (%d)\n", ret); + goto out; + } - switch (key_cmd) { - case Opt_load: - if (tpm2) - ret = tpm_unseal_trusted(chip, payload, options); - else - ret = key_unseal(payload, options); - dump_payload(payload); - dump_options(options); - if (ret < 0) - pr_info("trusted_key: key_unseal failed (%d)\n", ret); - break; - case Opt_new: - key_len = payload->key_len; - ret = tpm_get_random(chip, payload->key, key_len); - if (ret != key_len) { - pr_info("trusted_key: key_create failed (%d)\n", ret); + if (options->pcrlock) { + ret = pcrlock(options->pcrlock); + if (ret < 0) { + pr_info("tpm_trusted_key: pcrlock failed (%d)\n", ret); goto out; } - if (tpm2) - ret = tpm_seal_trusted(chip, payload, options); - else - ret = key_seal(payload, options); - if (ret < 0) - pr_info("trusted_key: key_seal failed (%d)\n", ret); - break; - default: - ret = -EINVAL; - goto out; } - if (!ret && options->pcrlock) - ret = pcrlock(options->pcrlock); out: - kzfree(datablob); kzfree(options); - if (!ret) - rcu_assign_keypointer(key, payload); - else - kzfree(payload); return ret; } -static void trusted_rcu_free(struct rcu_head *rcu) -{ - struct trusted_key_payload *p; - - p = container_of(rcu, struct trusted_key_payload, rcu); - kzfree(p); -} - -/* - * trusted_update - reseal an existing key with new PCR values - */ -static int trusted_update(struct key *key, struct key_preparsed_payload *prep) +static int tpm_tk_unseal(struct trusted_key_payload *p, char *datablob) { - struct trusted_key_payload *p; - struct trusted_key_payload *new_p; - struct trusted_key_options *new_o; - size_t datalen = prep->datalen; - char *datablob; + struct trusted_key_options *options = NULL; int ret = 0; + int tpm2; - if (key_is_negative(key)) - return -ENOKEY; - p = key->payload.data[0]; - if (!p->migratable) - return -EPERM; - if (datalen <= 0 || datalen > 32767 || !prep->data) - return -EINVAL; + tpm2 = tpm_is_tpm2(chip); + if (tpm2 < 0) + return tpm2; - datablob = kmalloc(datalen + 1, GFP_KERNEL); - if (!datablob) + options = trusted_options_alloc(); + if (!options) return -ENOMEM; - new_o = trusted_options_alloc(); - if (!new_o) { - ret = -ENOMEM; - goto out; - } - new_p = trusted_payload_alloc(key); - if (!new_p) { - ret = -ENOMEM; - goto out; - } - memcpy(datablob, prep->data, datalen); - datablob[datalen] = '\0'; - ret = datablob_parse(datablob, new_p, new_o); - if (ret != Opt_update) { - ret = -EINVAL; - kzfree(new_p); + ret = getoptions(datablob, p, options); + if (ret < 0) goto out; - } + dump_options(options); - if (!new_o->keyhandle) { + if (!options->keyhandle) { ret = -EINVAL; - kzfree(new_p); goto out; } - /* copy old key values, and reseal with new pcrs */ - new_p->migratable = p->migratable; - new_p->key_len = p->key_len; - memcpy(new_p->key, p->key, p->key_len); - dump_payload(p); - dump_payload(new_p); + if (tpm2) + ret = tpm_unseal_trusted(chip, p, options); + else + ret = key_unseal(p, options); + if (ret < 0) + pr_info("tpm_trusted_key: key_unseal failed (%d)\n", ret); - ret = key_seal(new_p, new_o); - if (ret < 0) { - pr_info("trusted_key: key_seal failed (%d)\n", ret); - kzfree(new_p); - goto out; - } - if (new_o->pcrlock) { - ret = pcrlock(new_o->pcrlock); + if (options->pcrlock) { + ret = pcrlock(options->pcrlock); if (ret < 0) { - pr_info("trusted_key: pcrlock failed (%d)\n", ret); - kzfree(new_p); + pr_info("tpm_trusted_key: pcrlock failed (%d)\n", ret); goto out; } } - rcu_assign_keypointer(key, new_p); - call_rcu(&p->rcu, trusted_rcu_free); out: - kzfree(datablob); - kzfree(new_o); + kzfree(options); return ret; } -/* - * trusted_read - copy the sealed blob data to userspace in hex. - * On success, return to userspace the trusted key datablob size. - */ -static long trusted_read(const struct key *key, char __user *buffer, - size_t buflen) -{ - const struct trusted_key_payload *p; - char *ascii_buf; - char *bufp; - int i; - - p = dereference_key_locked(key); - if (!p) - return -EINVAL; - - if (buffer && buflen >= 2 * p->blob_len) { - ascii_buf = kmalloc_array(2, p->blob_len, GFP_KERNEL); - if (!ascii_buf) - return -ENOMEM; - - bufp = ascii_buf; - for (i = 0; i < p->blob_len; i++) - bufp = hex_byte_pack(bufp, p->blob[i]); - if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) { - kzfree(ascii_buf); - return -EFAULT; - } - kzfree(ascii_buf); - } - return 2 * p->blob_len; -} - -/* - * trusted_destroy - clear and free the key's payload - */ -static void trusted_destroy(struct key *key) +int tpm_tk_get_random(unsigned char *key, size_t key_len) { - kzfree(key->payload.data[0]); + return tpm_get_random(chip, key, key_len); } -struct key_type key_type_trusted = { - .name = "trusted", - .instantiate = trusted_instantiate, - .update = trusted_update, - .destroy = trusted_destroy, - .describe = user_describe, - .read = trusted_read, -}; - -EXPORT_SYMBOL_GPL(key_type_trusted); - static void trusted_shash_release(void) { if (hashalg) @@ -1194,14 +963,14 @@ static int __init trusted_shash_alloc(void) hmacalg = crypto_alloc_shash(hmac_alg, 0, 0); if (IS_ERR(hmacalg)) { - pr_info("trusted_key: could not allocate crypto %s\n", + pr_info("tpm_trusted_key: could not allocate crypto %s\n", hmac_alg); return PTR_ERR(hmacalg); } hashalg = crypto_alloc_shash(hash_alg, 0, 0); if (IS_ERR(hashalg)) { - pr_info("trusted_key: could not allocate crypto %s\n", + pr_info("tpm_trusted_key: could not allocate crypto %s\n", hash_alg); ret = PTR_ERR(hashalg); goto hashalg_fail; @@ -1237,16 +1006,13 @@ static int __init init_digests(void) return 0; } -static int __init init_trusted(void) +static int __init init_tpm_trusted(void) { int ret; - /* encrypted_keys.ko depends on successful load of this module even if - * TPM is not used. - */ chip = tpm_default_chip(); if (!chip) - return 0; + return -ENODEV; ret = init_digests(); if (ret < 0) @@ -1267,7 +1033,7 @@ static int __init init_trusted(void) return ret; } -static void __exit cleanup_trusted(void) +static void __exit cleanup_tpm_trusted(void) { if (chip) { put_device(&chip->dev); @@ -1277,7 +1043,12 @@ static void __exit cleanup_trusted(void) } } -late_initcall(init_trusted); -module_exit(cleanup_trusted); - -MODULE_LICENSE("GPL"); +struct trusted_key_ops tpm_trusted_key_ops = { + .migratable = 1, /* migratable by default */ + .init = init_tpm_trusted, + .seal = tpm_tk_seal, + .unseal = tpm_tk_unseal, + .get_random = tpm_tk_get_random, + .cleanup = cleanup_tpm_trusted, +}; +EXPORT_SYMBOL_GPL(tpm_trusted_key_ops);