From patchwork Fri Jun 1 23:02:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Garrett X-Patchwork-Id: 10444413 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id F14FB601E9 for ; Fri, 1 Jun 2018 23:03:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DFFC928B1C for ; Fri, 1 Jun 2018 23:03:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D12B728B1D; Fri, 1 Jun 2018 23:03: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=-15.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI, USER_IN_DEF_DKIM_WL 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 2BF4E28B0F for ; Fri, 1 Jun 2018 23:03:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750931AbeFAXDD (ORCPT ); Fri, 1 Jun 2018 19:03:03 -0400 Received: from mail-yw0-f201.google.com ([209.85.161.201]:36433 "EHLO mail-yw0-f201.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750881AbeFAXDC (ORCPT ); Fri, 1 Jun 2018 19:03:02 -0400 Received: by mail-yw0-f201.google.com with SMTP id l36-v6so18054758ywa.3 for ; Fri, 01 Jun 2018 16:03:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=mime-version:date:in-reply-to:message-id:references:subject:from:to :cc; bh=5uB9bbIhi0aNBm1E3mSRUkbBjXDkyOKLCkyMJJ3jFMY=; b=Dbo7Tpj2KCei4bM91wewg6eNm6OChkCYZyvBj9h9xtEvD8cFAFtPAF8X1GD+/eQjZH 4LCQyUBequToe8K67uzxW2Jz72xb0ZD2PV7z5ilq1Jqmo4eFcAA3E0KVBdpY8GeSB4Gy ylNihN5sma/M1E5jrFM7+AZAmKLn2vxZI3bMDCW57izL63KRFcFkqhOwgnP/LArze0jW bd7kQ2g34jPwAB0h7/YomFXvoDCD6fO+qYRkulpD8cUFWn0I3Wccad96ckkfZPiXG6kB ZQfO1ApZpCTWKFbl0xbnFrW9+Mqvk7OtWTuxtO0+6+IvO91k9sUZ1Q+QxqxTQBM6ETY0 A/hg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:date:in-reply-to:message-id :references:subject:from:to:cc; bh=5uB9bbIhi0aNBm1E3mSRUkbBjXDkyOKLCkyMJJ3jFMY=; b=Z+h1krFWuPTuEBIiI5173GYiSZFKXr6pcDFyZCKW3Hu1spekrpKwLpBX0KDV+9B+go 97bQ7OJTFGdwCECiCGlyxP30uHWGUXFjalTJM3DxdqVMNssDRPfI+OPOUxI9PqjkWPLV Dyj8miVJQtzhUHYqy7rKKfwrkYjY4UPEiRdxFpqJcFYXNbMFadAfhmLnmeKxXlrzed2S Lef0HW69oOCLMt04yN7wUZpilWFjjgAsDX4iJfxi4zKj9LW00igAHa1ZUqgkHA2OG39K gpOE3eMm0vA/3vpJkKgOutcb2k0SnK78eDF6Bj6yv1vwOEfIB2Zt5MrOrO5jPPOgEVNU Htcg== X-Gm-Message-State: ALKqPweg6fIXspIABbbfVAPajhZQbiGybQN2oEsIj0Psb7IrYq4zkuxQ HkctSgdr1cQ4bDDDFtKKTAbw5q0auilCPKHysUu/ZYKeqPfUZQPrswAxbpXU0Hi1lsZdrbJRFHk ejb58LojKItVOpNgMQSZGQTdU+0G2kDg3Cvg= X-Google-Smtp-Source: ADUXVKI++HXrpreWHvjlrj4D6hBJ51kZ+MTgCxHuUnmWOLQYXiIPNbdwAejw5U+Ww0/ehhMxO7I3O0Z6OKstwvzqcuLbqA== MIME-Version: 1.0 X-Received: by 2002:a0d:ea09:: with SMTP id t9-v6mr3497598ywe.9.1527894182081; Fri, 01 Jun 2018 16:03:02 -0700 (PDT) Date: Fri, 1 Jun 2018 16:02:44 -0700 In-Reply-To: <20180601230244.138560-1-mjg59@google.com> Message-Id: <20180601230244.138560-2-mjg59@google.com> References: <20180601230244.138560-1-mjg59@google.com> X-Mailer: git-send-email 2.17.1.1185.g55be947832-goog Subject: [PATCH 2/2] evm: Allow non-SHA1 digital signatures From: Matthew Garrett To: linux-integrity@vger.kernel.org Cc: zohar@linux.vnet.ibm.com, linux-crypto@vger.kernel.org, herbert@gondor.apana.org.au, davem@davemloft.net, Matthew Garrett Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP SHA1 is reasonable in HMAC constructs, but it's desirable to be able to use stronger hashes in digital signatures. Modify the EVM crypto code so the hash type is imported from the digital signature and passed down to the hash calculation code, and return the digest size to higher layers for validation. Signed-off-by: Matthew Garrett --- security/integrity/evm/evm.h | 10 ++++-- security/integrity/evm/evm_crypto.c | 47 +++++++++++++++-------------- security/integrity/evm/evm_main.c | 19 +++++++----- 3 files changed, 45 insertions(+), 31 deletions(-) diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h index 45c4a89c02ff..a8289fbf2f0c 100644 --- a/security/integrity/evm/evm.h +++ b/security/integrity/evm/evm.h @@ -42,6 +42,11 @@ extern struct crypto_shash *hash_tfm; /* List of EVM protected security xattrs */ extern char *evm_config_xattrnames[]; +struct evm_digest { + struct ima_digest_data hdr; + char digest[IMA_MAX_DIGEST_SIZE]; +} __packed; + int evm_init_key(void); int evm_update_evmxattr(struct dentry *dentry, const char *req_xattr_name, @@ -49,10 +54,11 @@ int evm_update_evmxattr(struct dentry *dentry, size_t req_xattr_value_len); int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name, const char *req_xattr_value, - size_t req_xattr_value_len, char *digest); + size_t req_xattr_value_len, struct evm_digest *data); int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name, const char *req_xattr_value, - size_t req_xattr_value_len, char type, char *digest); + size_t req_xattr_value_len, char type, + struct evm_digest *data); int evm_init_hmac(struct inode *inode, const struct xattr *xattr, char *hmac_val); int evm_init_secfs(void); diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c index ccafc9468611..ff8687232a1a 100644 --- a/security/integrity/evm/evm_crypto.c +++ b/security/integrity/evm/evm_crypto.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "evm.h" #define EVMKEY "evm-key" @@ -29,7 +30,7 @@ static unsigned char evmkey[MAX_KEY_SIZE]; static int evmkey_len = MAX_KEY_SIZE; struct crypto_shash *hmac_tfm; -struct crypto_shash *hash_tfm; +static struct crypto_shash *evm_tfm[HASH_ALGO__LAST]; static DEFINE_MUTEX(mutex); @@ -38,7 +39,6 @@ static DEFINE_MUTEX(mutex); static unsigned long evm_set_key_flags; static char * const evm_hmac = "hmac(sha1)"; -static char * const evm_hash = "sha1"; /** * evm_set_key() - set EVM HMAC key from the kernel @@ -74,10 +74,10 @@ int evm_set_key(void *key, size_t keylen) } EXPORT_SYMBOL_GPL(evm_set_key); -static struct shash_desc *init_desc(char type) +static struct shash_desc *init_desc(char type, uint8_t hash_algo) { long rc; - char *algo; + const char *algo; struct crypto_shash **tfm; struct shash_desc *desc; @@ -89,8 +89,8 @@ static struct shash_desc *init_desc(char type) tfm = &hmac_tfm; algo = evm_hmac; } else { - tfm = &hash_tfm; - algo = evm_hash; + tfm = &evm_tfm[hash_algo]; + algo = hash_algo_name[hash_algo]; } if (*tfm == NULL) { @@ -187,10 +187,10 @@ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode, * each xattr, but attempt to re-use the previously allocated memory. */ static int evm_calc_hmac_or_hash(struct dentry *dentry, - const char *req_xattr_name, - const char *req_xattr_value, - size_t req_xattr_value_len, - char type, char *digest) + const char *req_xattr_name, + const char *req_xattr_value, + size_t req_xattr_value_len, + uint8_t type, struct evm_digest *data) { struct inode *inode = d_backing_inode(dentry); struct shash_desc *desc; @@ -204,10 +204,12 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry, if (!(inode->i_opflags & IOP_XATTR)) return -EOPNOTSUPP; - desc = init_desc(type); + desc = init_desc(type, data->hdr.algo); if (IS_ERR(desc)) return PTR_ERR(desc); + data->hdr.length = crypto_shash_digestsize(desc->tfm); + error = -ENODATA; for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) { bool is_ima = false; @@ -239,7 +241,7 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry, if (is_ima) ima_present = true; } - hmac_add_misc(desc, inode, type, digest); + hmac_add_misc(desc, inode, type, data->digest); /* Portable EVM signatures must include an IMA hash */ if (type == EVM_XATTR_PORTABLE_DIGSIG && !ima_present) @@ -252,18 +254,18 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry, int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name, const char *req_xattr_value, size_t req_xattr_value_len, - char *digest) + struct evm_digest *data) { return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value, - req_xattr_value_len, EVM_XATTR_HMAC, digest); + req_xattr_value_len, EVM_XATTR_HMAC, data); } int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name, const char *req_xattr_value, size_t req_xattr_value_len, - char type, char *digest) + char type, struct evm_digest *data) { return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value, - req_xattr_value_len, type, digest); + req_xattr_value_len, type, data); } static int evm_is_immutable(struct dentry *dentry, struct inode *inode) @@ -303,7 +305,7 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name, const char *xattr_value, size_t xattr_value_len) { struct inode *inode = d_backing_inode(dentry); - struct evm_ima_xattr_data xattr_data; + struct evm_digest data; int rc = 0; /* @@ -316,13 +318,14 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name, if (rc) return -EPERM; + data.hdr.algo = HASH_ALGO_SHA1; rc = evm_calc_hmac(dentry, xattr_name, xattr_value, - xattr_value_len, xattr_data.digest); + xattr_value_len, &data); if (rc == 0) { - xattr_data.type = EVM_XATTR_HMAC; + data.hdr.xattr.sha1.type = EVM_XATTR_HMAC; rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM, - &xattr_data, - sizeof(xattr_data), 0); + &data.hdr.xattr.data[1], + SHA1_DIGEST_SIZE + 1, 0); } else if (rc == -ENODATA && (inode->i_opflags & IOP_XATTR)) { rc = __vfs_removexattr(dentry, XATTR_NAME_EVM); } @@ -334,7 +337,7 @@ int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr, { struct shash_desc *desc; - desc = init_desc(EVM_XATTR_HMAC); + desc = init_desc(EVM_XATTR_HMAC, HASH_ALGO_SHA1); if (IS_ERR(desc)) { pr_info("init_desc failed\n"); return PTR_ERR(desc); diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index 9ea9c19a545c..88ea9c1962d6 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -25,6 +25,7 @@ #include #include +#include #include #include "evm.h" @@ -122,8 +123,9 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry, struct integrity_iint_cache *iint) { struct evm_ima_xattr_data *xattr_data = NULL; - struct evm_ima_xattr_data calc; + struct signature_v2_hdr *hdr; enum integrity_status evm_status = INTEGRITY_PASS; + struct evm_digest digest; struct inode *inode; int rc, xattr_len; @@ -159,25 +161,28 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry, evm_status = INTEGRITY_FAIL; goto out; } + + digest.hdr.algo = HASH_ALGO_SHA1; rc = evm_calc_hmac(dentry, xattr_name, xattr_value, - xattr_value_len, calc.digest); + xattr_value_len, &digest); if (rc) break; - rc = crypto_memneq(xattr_data->digest, calc.digest, - sizeof(calc.digest)); + rc = crypto_memneq(xattr_data->digest, digest.digest, + SHA1_DIGEST_SIZE); if (rc) rc = -EINVAL; break; case EVM_IMA_XATTR_DIGSIG: case EVM_XATTR_PORTABLE_DIGSIG: + hdr = (struct signature_v2_hdr *)xattr_data; + digest.hdr.algo = hdr->hash_algo; rc = evm_calc_hash(dentry, xattr_name, xattr_value, - xattr_value_len, xattr_data->type, - calc.digest); + xattr_value_len, xattr_data->type, &digest); if (rc) break; rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM, (const char *)xattr_data, xattr_len, - calc.digest, sizeof(calc.digest)); + digest.digest, digest.hdr.length); if (!rc) { inode = d_backing_inode(dentry);