Received: by 10.213.65.68 with SMTP id h4csp628097imn; Fri, 16 Mar 2018 13:46:28 -0700 (PDT) X-Google-Smtp-Source: AG47ELuxaNBKjXeFnYHlfh5NU8yIai7xyUglIcEnvwXXdlqK7lRodm+1COtkq/0XdP7v1ba5JeqR X-Received: by 10.98.8.92 with SMTP id c89mr2715925pfd.154.1521233188872; Fri, 16 Mar 2018 13:46:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1521233188; cv=none; d=google.com; s=arc-20160816; b=D5ObuMj9JOZFep+GgqHYxQ5aKfIez+mYoz0cmJQhoDSt0FHobe1IbzcVVMqPpsI/Bm nPB1HE9C+2ol25+QS0rpKThflkMxD8f5rQewyxkQQEwxZFkX/C5ppAHmfT89Q2tMnyw0 siRyj4Iy0uBpfOwXiiGAcMVqVgIOp0wClsOC6KHf3Fz8OkNxDr9IqhuhoE47jRBGlmlS 6zu3kb6d1IhorUOhlJZ3lZBo6tSbB2I3XI/idJVJAPYsbsRKD28u4TTGNO0bpVr1mSX2 NwpQQyoQBCJF5yRwAK8YOQi/iFtEFTIY+3FY9RZm8hAQZes9n6tgBayeOorJ4CwW4U9Z 5qiw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:references:in-reply-to:date :subject:cc:to:from:arc-authentication-results; bh=RgHdrW6dJa6lBEWrFPsq7jbtVCQ9DX/HF2XOj0BQwvA=; b=fvGIO6EUCCWkLCMXFxaj8kE8dZ2EvMjtftKTnlTSmxazYti4FVI6Vq7By7TFC4yXCd RWFO8TXHCTQo8yQ0/vwtZlCuIzpJcj4JA2uecYEREcF+6Iuw5ptjC59TEtp5S3rOvj1v mFP9o2fer7xjTBKFMau2qmK6rMEO12jp9wNUIx220jt3wIDv/o+Q/66cWTY3aHtwchUu ByIW6tr9RLpe9eDJpoDNVCFI09osLBezHrD4cMz0d2qJqIQ90x0urIS53BWAMxKC3gHV tB3GwBM5Qnh7aCmYUaWR7sU+yqW5lOcKIyQpmzMlKcFAAJw34Y/DIU48vq+velCvmnhq 4p4g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=ibm.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h90-v6si6946339plb.400.2018.03.16.13.46.15; Fri, 16 Mar 2018 13:46:28 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=ibm.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753520AbeCPUpU (ORCPT + 99 others); Fri, 16 Mar 2018 16:45:20 -0400 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:38026 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750991AbeCPUpT (ORCPT ); Fri, 16 Mar 2018 16:45:19 -0400 Received: from pps.filterd (m0098404.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w2GKhfep146189 for ; Fri, 16 Mar 2018 16:45:18 -0400 Received: from e34.co.us.ibm.com (e34.co.us.ibm.com [32.97.110.152]) by mx0a-001b2d01.pphosted.com with ESMTP id 2grmbn9put-1 (version=TLSv1.2 cipher=AES256-SHA256 bits=256 verify=NOT) for ; Fri, 16 Mar 2018 16:45:18 -0400 Received: from localhost by e34.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 16 Mar 2018 14:40:17 -0600 Received: from b03cxnp07028.gho.boulder.ibm.com (9.17.130.15) by e34.co.us.ibm.com (192.168.1.134) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Fri, 16 Mar 2018 14:40:12 -0600 Received: from b03ledav004.gho.boulder.ibm.com (b03ledav004.gho.boulder.ibm.com [9.17.130.235]) by b03cxnp07028.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w2GKeBs211534744; Fri, 16 Mar 2018 13:40:11 -0700 Received: from b03ledav004.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id C412378047; Fri, 16 Mar 2018 14:40:11 -0600 (MDT) Received: from morokweng.localdomain.com (unknown [9.85.199.230]) by b03ledav004.gho.boulder.ibm.com (Postfix) with ESMTP id A6B4F78038; Fri, 16 Mar 2018 14:40:07 -0600 (MDT) From: Thiago Jung Bauermann To: linux-integrity@vger.kernel.org Cc: linux-security-module@vger.kernel.org, keyrings@vger.kernel.org, linux-crypto@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org, Mimi Zohar , Dmitry Kasatkin , James Morris , "Serge E. Hallyn" , David Howells , David Woodhouse , Jessica Yu , Herbert Xu , "David S. Miller" , "AKASHI, Takahiro" , Thiago Jung Bauermann Subject: [PATCH v6 10/12] ima: Add functions to read and verify a modsig signature Date: Fri, 16 Mar 2018 17:38:35 -0300 X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180316203837.10174-1-bauerman@linux.vnet.ibm.com> References: <20180316203837.10174-1-bauerman@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 18031620-0016-0000-0000-00000867DF4E X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008686; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000254; SDB=6.01004029; UDB=6.00511020; IPR=6.00783318; MB=3.00020079; MTD=3.00000008; XFM=3.00000015; UTC=2018-03-16 20:40:16 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18031620-0017-0000-0000-00003DDF26D0 Message-Id: <20180316203837.10174-11-bauerman@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:,, definitions=2018-03-16_13:,, signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=3 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1803160244 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This is the code needed by IMA-appraise to work with modsig signatures. It will be used by the next two patches. Signed-off-by: Thiago Jung Bauermann --- security/integrity/ima/Kconfig | 3 + security/integrity/ima/ima.h | 41 ++++++++ security/integrity/ima/ima_modsig.c | 181 ++++++++++++++++++++++++++++++++++++ security/integrity/integrity.h | 1 + 4 files changed, 226 insertions(+) diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index ee278189e0bb..306601d62f0b 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -167,6 +167,9 @@ config IMA_APPRAISE_BOOTPARAM config IMA_APPRAISE_MODSIG bool "Support module-style signatures for appraisal" depends on IMA_APPRAISE + depends on INTEGRITY_ASYMMETRIC_KEYS + select PKCS7_MESSAGE_PARSER + select MODULE_SIG_FORMAT default n help Adds support for signatures appended to files. The format of the diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index c61d8fc5190d..49aef56dc96d 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -301,11 +301,52 @@ static inline int ima_read_xattr(struct dentry *dentry, #ifdef CONFIG_IMA_APPRAISE_MODSIG bool ima_hook_supports_modsig(enum ima_hooks func); +int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len, + struct evm_ima_xattr_data **xattr_value, + int *xattr_len); +int ima_get_modsig_hash(struct evm_ima_xattr_data *hdr, enum hash_algo *algo, + const u8 **hash, u8 *len); +int ima_modsig_serialize_data(struct evm_ima_xattr_data **data, int *data_len); +int ima_modsig_verify(const unsigned int keyring_id, + struct evm_ima_xattr_data *hdr); +void ima_free_xattr_data(struct evm_ima_xattr_data *hdr); #else static inline bool ima_hook_supports_modsig(enum ima_hooks func) { return false; } + +static inline int ima_read_modsig(enum ima_hooks func, const void *buf, + loff_t buf_len, + struct evm_ima_xattr_data **xattr_value, + int *xattr_len) +{ + return -ENOTSUPP; +} + +static inline int ima_get_modsig_hash(struct evm_ima_xattr_data *hdr, + enum hash_algo *algo, const u8 **hash, + u8 *len) +{ + return -ENOTSUPP; +} + +static inline int ima_modsig_serialize_data(struct evm_ima_xattr_data **data, + int *data_len) +{ + return -ENOTSUPP; +} + +static inline int ima_modsig_verify(const unsigned int keyring_id, + struct evm_ima_xattr_data *hdr) +{ + return -ENOTSUPP; +} + +static inline void ima_free_xattr_data(struct evm_ima_xattr_data *hdr) +{ + kfree(hdr); +} #endif /* CONFIG_IMA_APPRAISE_MODSIG */ /* LSM based policy rules require audit */ diff --git a/security/integrity/ima/ima_modsig.c b/security/integrity/ima/ima_modsig.c index d8ea811b6f74..105fd04d585e 100644 --- a/security/integrity/ima/ima_modsig.c +++ b/security/integrity/ima/ima_modsig.c @@ -8,8 +8,25 @@ * Thiago Jung Bauermann */ +#include +#include +#include +#include + #include "ima.h" +struct modsig_hdr { + uint8_t type; /* Should be IMA_MODSIG. */ + struct pkcs7_message *pkcs7_msg; + int raw_pkcs7_len; + + /* + * This is what will go to the measurement list if the template requires + * storing the signature. + */ + struct evm_ima_xattr_data raw_pkcs7; +}; + /** * ima_hook_supports_modsig - can the policy allow modsig for this hook? * @@ -29,3 +46,167 @@ bool ima_hook_supports_modsig(enum ima_hooks func) return false; } } + +static bool modsig_has_known_key(struct modsig_hdr *hdr) +{ + const struct public_key_signature *pks; + struct key *keyring; + struct key *key; + + keyring = integrity_keyring_from_id(INTEGRITY_KEYRING_IMA); + if (IS_ERR(keyring)) + return false; + + pks = pkcs7_get_message_sig(hdr->pkcs7_msg); + if (!pks) + return false; + + key = find_asymmetric_key(keyring, pks->auth_ids[0], NULL, false); + if (IS_ERR(key)) + return false; + + key_put(key); + + return true; +} + +int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len, + struct evm_ima_xattr_data **xattr_value, + int *xattr_len) +{ + const size_t marker_len = sizeof(MODULE_SIG_STRING) - 1; + const struct module_signature *sig; + struct modsig_hdr *hdr; + size_t sig_len; + const void *p; + int rc; + + /* + * Not supposed to happen. Hooks that support modsig are whitelisted + * when parsing the policy using ima_hooks_supports_modsig(). + */ + if (!buf || !buf_len) { + WARN_ONCE(true, "%s doesn't support modsig\n", + func_tokens[func]); + return -ENOENT; + } else if (buf_len <= marker_len + sizeof(*sig)) + return -ENOENT; + + p = buf + buf_len - marker_len; + if (memcmp(p, MODULE_SIG_STRING, marker_len)) + return -ENOENT; + + buf_len -= marker_len; + sig = (const struct module_signature *) (p - sizeof(*sig)); + + rc = validate_module_sig(sig, buf_len); + if (rc) + return rc; + + sig_len = be32_to_cpu(sig->sig_len); + buf_len -= sig_len + sizeof(*sig); + + /* Allocate sig_len additional bytes to hold the raw PKCS#7 data. */ + hdr = kmalloc(sizeof(*hdr) + sig_len, GFP_KERNEL); + if (!hdr) + return -ENOMEM; + + hdr->pkcs7_msg = pkcs7_parse_message(buf + buf_len, sig_len); + if (IS_ERR(hdr->pkcs7_msg)) { + rc = PTR_ERR(hdr->pkcs7_msg); + goto err_no_msg; + } + + rc = pkcs7_supply_detached_data(hdr->pkcs7_msg, buf, buf_len); + if (rc) + goto err; + + if (!modsig_has_known_key(hdr)) { + rc = -ENOKEY; + goto err; + } + + memcpy(hdr->raw_pkcs7.data, buf + buf_len, sig_len); + hdr->raw_pkcs7_len = sig_len + 1; + hdr->raw_pkcs7.type = IMA_MODSIG; + + hdr->type = IMA_MODSIG; + + *xattr_value = (typeof(*xattr_value)) hdr; + *xattr_len = sizeof(*hdr); + + return 0; + + err: + pkcs7_free_message(hdr->pkcs7_msg); + err_no_msg: + kfree(hdr); + return rc; +} + +int ima_get_modsig_hash(struct evm_ima_xattr_data *hdr, enum hash_algo *algo, + const u8 **hash, u8 *len) +{ + struct modsig_hdr *modsig = (typeof(modsig)) hdr; + const struct public_key_signature *pks; + int i; + + if (!hdr || hdr->type != IMA_MODSIG) + return -EINVAL; + + pks = pkcs7_get_message_sig(modsig->pkcs7_msg); + if (!pks) + return -EBADMSG; + + for (i = 0; i < HASH_ALGO__LAST; i++) + if (!strcmp(hash_algo_name[i], pks->hash_algo)) + break; + + *algo = i; + + return pkcs7_get_digest(modsig->pkcs7_msg, hash, len); +} + +int ima_modsig_serialize_data(struct evm_ima_xattr_data **data, int *data_len) +{ + struct modsig_hdr *modsig = (struct modsig_hdr *) *data; + + if (!*data || (*data)->type != IMA_MODSIG) + return -EINVAL; + + *data = &modsig->raw_pkcs7; + *data_len = modsig->raw_pkcs7_len; + + return 0; +} + +int ima_modsig_verify(const unsigned int keyring_id, + struct evm_ima_xattr_data *hdr) +{ + struct modsig_hdr *modsig = (struct modsig_hdr *) hdr; + struct key *keyring; + + if (!hdr || hdr->type != IMA_MODSIG) + return -EINVAL; + + keyring = integrity_keyring_from_id(keyring_id); + if (IS_ERR(keyring)) + return PTR_ERR(keyring); + + return verify_pkcs7_message_sig(NULL, 0, modsig->pkcs7_msg, keyring, + VERIFYING_MODULE_SIGNATURE, NULL, NULL); +} + +void ima_free_xattr_data(struct evm_ima_xattr_data *hdr) +{ + if (!hdr) + return; + + if (hdr->type == IMA_MODSIG) { + struct modsig_hdr *modsig = (struct modsig_hdr *) hdr; + + pkcs7_free_message(modsig->pkcs7_msg); + } + + kfree(hdr); +} diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 6643c6550787..4acb1fb86b3b 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -74,6 +74,7 @@ enum evm_ima_xattr_type { EVM_IMA_XATTR_DIGSIG, IMA_XATTR_DIGEST_NG, EVM_XATTR_PORTABLE_DIGSIG, + IMA_MODSIG, IMA_XATTR_LAST };