From patchwork Thu Mar 16 14:39:40 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Broz X-Patchwork-Id: 9628413 X-Patchwork-Delegate: snitzer@redhat.com 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 40DE360244 for ; Thu, 16 Mar 2017 14:40:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 32E642866F for ; Thu, 16 Mar 2017 14:40:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 27AAD28674; Thu, 16 Mar 2017 14:40:16 +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=-6.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 7381328643 for ; Thu, 16 Mar 2017 14:40:15 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 175EB4E4DE; Thu, 16 Mar 2017 14:40:14 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 175EB4E4DE Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=dm-devel-bounces@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 175EB4E4DE Authentication-Results: mx1.redhat.com; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Exuh4HDT" Received: from colo-mx.corp.redhat.com (unknown [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id E8EF018B36; Thu, 16 Mar 2017 14:40:12 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 9341C5EC61; Thu, 16 Mar 2017 14:40:11 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v2GEe9je029434 for ; Thu, 16 Mar 2017 10:40:09 -0400 Received: by smtp.corp.redhat.com (Postfix) id CDF0891296; Thu, 16 Mar 2017 14:40:09 +0000 (UTC) Delivered-To: dm-devel@redhat.com Received: from mx1.redhat.com (ext-mx03.extmail.prod.ext.phx2.redhat.com [10.5.110.27]) by smtp.corp.redhat.com (Postfix) with ESMTPS id C79445C6C9 for ; Thu, 16 Mar 2017 14:40:06 +0000 (UTC) Received: from mail-wr0-f195.google.com (mail-wr0-f195.google.com [209.85.128.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 39461804E4 for ; Thu, 16 Mar 2017 14:40:05 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 39461804E4 Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=gmazyland@gmail.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 39461804E4 Received: by mail-wr0-f195.google.com with SMTP id u108so6192536wrb.2 for ; Thu, 16 Mar 2017 07:40:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=BLDq9Q5xpwYXf1bdTi4VEJwYJeiF+HOu9mFQbCu5JGo=; b=Exuh4HDTxCA3Cj5uFdnUmXZlocOHUKye6J43PLZHotA6dmpBZyrT0n4ammtYcGy/1j 7OnXta3gedqczuIe1f6vjWKWCZ4tjK3dTGW9YjG4AIzX2JQDm2hOH/N0lw4VNhWxaIly UYpW6BevglbSsiNzYL4Zw2tNnMyvBo/4wwLRKhhAlg8moicFAFKc6VPudcELHe4XsKSC odCHYNq2huhkuD1S+9aMiFkOR7kRRMOU8EfwVpvmyvFmpC69+67+w9nEzoF4B/n5WMbL MsMeLE7OJbCYi8tzYwMYQfggw2Bsa2G0X2KvzyU4H/KzOXDHo0ONL2w5fkvE8IxU9tPC tsXw== 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:in-reply-to:references; bh=BLDq9Q5xpwYXf1bdTi4VEJwYJeiF+HOu9mFQbCu5JGo=; b=kppsFXRVuQBcKqqb+bucXEyO6WRHZpuHnBY1HuG4PUb09jmwCu9j3pzvMPIMgfhKZS Az1J+zNjk5CP25RzGClh2NdSWe+MQyv8hj3AGuXpfWJg2lQvldcl+5hOxYFtZhRoUh7i nKkPjNdVCYrIAqtqOCajsYWzGrudzEucKb1EOgHmJ6/XW4+pbnpQrcKiewCl2HNVbvS2 iGeSiSZREtoEOlB2EW6+OH7rAACcFlFbcYy9NPRcHY485AKT982xYTPILaOtVKcEL+pK k4+l14UBjwoWLQLkAVsNY6v5/SOK3gt9p4RV9bJlBjR8l6+r+OKSzfewvFPyh1qtMseP KgJQ== X-Gm-Message-State: AFeK/H0yxl268ArQAc/RwhrOGXpHhiGrghi3VVJLMeSGxv9j/98ATVvahDr91taRW50v4Q== X-Received: by 10.223.157.37 with SMTP id k37mr8428804wre.148.1489675202799; Thu, 16 Mar 2017 07:40:02 -0700 (PDT) Received: from merlot.mazyland.net (nat-pool-brq-t.redhat.com. [213.175.37.10]) by smtp.googlemail.com with ESMTPSA id i203sm4553466wmf.12.2017.03.16.07.40.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 16 Mar 2017 07:40:02 -0700 (PDT) From: Milan Broz To: dm-devel@redhat.com Date: Thu, 16 Mar 2017 15:39:40 +0100 Message-Id: <20170316143944.19843-4-gmazyland@gmail.com> In-Reply-To: <20170316143944.19843-1-gmazyland@gmail.com> References: <20170316143944.19843-1-gmazyland@gmail.com> In-Reply-To: References: X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Thu, 16 Mar 2017 14:40:05 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Thu, 16 Mar 2017 14:40:05 +0000 (UTC) for IP:'209.85.128.195' DOMAIN:'mail-wr0-f195.google.com' HELO:'mail-wr0-f195.google.com' FROM:'gmazyland@gmail.com' RCPT:'' X-RedHat-Spam-Score: -1.71 (BAYES_50, DCC_REPUT_13_19, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, RCVD_IN_SORBS_SPAM, SPF_PASS) 209.85.128.195 mail-wr0-f195.google.com 209.85.128.195 mail-wr0-f195.google.com X-Scanned-By: MIMEDefang 2.78 on 10.5.110.27 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-loop: dm-devel@redhat.com Cc: Milan Broz Subject: [dm-devel] [PATCH 3/7] dm-crypt: Introduce new format of cipher with capi: prefix. X-BeenThere: dm-devel@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: device-mapper development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dm-devel-bounces@redhat.com Errors-To: dm-devel-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Thu, 16 Mar 2017 14:40:15 +0000 (UTC) X-Virus-Scanned: ClamAV using ClamSMTP For the new authenticated encryption we have to support generic composed modes (combination of encryption algorithm anf authenticator) because this is the way how kernel crypto API accesses such algorithms. To simplify interface, we accept an algorithm directly in crypto API format. The new format is recognised by the "capi:" prefix. The dmcrypt internal IV specification is the same as for the old format. The crypto API cipher specifications format is: capi:cipher_api_spec-ivmode[:ivopts] Examples: capi:cbc(aes)-essiv:sha256 (equivalent to old aes-cbc-essiv:sha256) capi:xts(aes)-plain64 (equivalent to old aes-xts-plain64) Examples of authenticated modes: capi:gcm(aes)-random capi:authenc(hmac(sha256),xts(aes))-random capi:rfc7539(chacha20,poly1305)-random Authenticated modes can be configured only by the new cipher format. Authenticated encryption algorithms can be of two types, either native modes (like GCM) that performs both encryption and authentication internally, and also composed mode where user can compose AEAD with separate specification of encryption algorithm and authenticator. Note that this policy allows user to specify arbitrary combination that can be insecure. (Policy decision is done in cryptsetup userspace.) (Note that HMAC composed modes requires following patches in series that are split for better readability of changes.) Signed-off-by: Milan Broz --- Documentation/device-mapper/dm-crypt.txt | 27 +++++-- drivers/md/dm-crypt.c | 134 +++++++++++++++++++++++++------ 2 files changed, 132 insertions(+), 29 deletions(-) diff --git a/Documentation/device-mapper/dm-crypt.txt b/Documentation/device-mapper/dm-crypt.txt index 058f26ddf875..8140b71f3c54 100644 --- a/Documentation/device-mapper/dm-crypt.txt +++ b/Documentation/device-mapper/dm-crypt.txt @@ -11,14 +11,31 @@ Parameters: \ [<#opt_params> ] - Encryption cipher and an optional IV generation mode. - (In format cipher[:keycount]-chainmode-ivmode[:ivopts]). + Encryption cipher, encryption mode and Initial Vector (IV) generator. + + The cipher specifications format is: + cipher[:keycount]-chainmode-ivmode[:ivopts] Examples: - des aes-cbc-essiv:sha256 - twofish-ecb + aes-xts-plain64 + serpent-xts-plain64 + + Cipher format also supports direct specification with kernel crypt API + format (selected by capi: prefix). The IV specification is the same + as for the first format type. + This format is mainly used for specification of authenticated modes. - /proc/crypto contains supported crypto modes + The crypto API cipher specifications format is: + capi:cipher_api_spec-ivmode[:ivopts] + Examples: + capi:cbc(aes)-essiv:sha256 + capi:xts(aes)-plain64 + Examples of authenticated modes: + capi:gcm(aes)-random + capi:authenc(hmac(sha256),xts(aes))-random + capi:rfc7539(chacha20,poly1305)-random + + The /proc/crypto contains a list of curently loaded crypto modes. Key used for encryption. It is encoded either as a hexadecimal number diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index faec408dcf50..0c7d07e17b81 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -2263,11 +2263,82 @@ static int crypt_ctr_ivmode(struct dm_target *ti, const char *ivmode) return 0; } -static int crypt_ctr_cipher(struct dm_target *ti, - char *cipher_in, char *key) +/* + * Workaround to parse cipher algorithm from crypto API spec. + * The cc->cipher is currently used only in ESSIV. + * This should be probably done by crypto-api calls (once available...) + */ +static int crypt_ctr_blkdev_cipher(struct crypt_config *cc) +{ + const char *alg_name = crypto_tfm_alg_name(crypto_skcipher_tfm(any_tfm(cc))); + char *start, *end; + + start = strchr(alg_name, '('); + end = strchr(alg_name, ')'); + + if (!start && !end) { + cc->cipher = kstrdup(alg_name, GFP_KERNEL); + return cc->cipher ? 0 : -ENOMEM; + } + + if (!start || !end || ++start >= end) + return -EINVAL; + + cc->cipher = kzalloc(end - start + 1, GFP_KERNEL); + if (!cc->cipher) + return -ENOMEM; + + strncpy(cc->cipher, start, end - start); + + return 0; +} + +static int crypt_ctr_cipher_new(struct dm_target *ti, char *cipher_in, char *key, + char **ivmode, char **ivopts) { struct crypt_config *cc = ti->private; - char *tmp, *cipher, *chainmode, *ivmode, *ivopts, *keycount; + char *tmp, *cipher_api; + int ret = -EINVAL; + + cc->tfms_count = 1; + + /* + * New format (capi: prefix) + * capi:cipher_api_spec-iv:ivopts + */ + tmp = &cipher_in[strlen("capi:")]; + cipher_api = strsep(&tmp, "-"); + *ivmode = strsep(&tmp, ":"); + *ivopts = tmp; + + if (*ivmode && !strcmp(*ivmode, "lmk")) + cc->tfms_count = 64; + + cc->key_parts = cc->tfms_count; + + /* Allocate cipher */ + ret = crypt_alloc_tfms(cc, cipher_api); + if (ret < 0) { + ti->error = "Error allocating crypto tfm"; + return ret; + } + + cc->iv_size = crypto_skcipher_ivsize(any_tfm(cc)); + + ret = crypt_ctr_blkdev_cipher(cc); + if (ret < 0) { + ti->error = "Cannot allocate cipher string"; + return -ENOMEM; + } + + return 0; +} + +static int crypt_ctr_cipher_old(struct dm_target *ti, char *cipher_in, char *key, + char **ivmode, char **ivopts) +{ + struct crypt_config *cc = ti->private; + char *tmp, *cipher, *chainmode, *keycount; char *cipher_api = NULL; int ret = -EINVAL; char dummy; @@ -2277,10 +2348,6 @@ static int crypt_ctr_cipher(struct dm_target *ti, return -EINVAL; } - cc->cipher_string = kstrdup(cipher_in, GFP_KERNEL); - if (!cc->cipher_string) - goto bad_mem; - /* * Legacy dm-crypt cipher specification * cipher[:keycount]-mode-iv:ivopts @@ -2303,8 +2370,8 @@ static int crypt_ctr_cipher(struct dm_target *ti, goto bad_mem; chainmode = strsep(&tmp, "-"); - ivopts = strsep(&tmp, "-"); - ivmode = strsep(&ivopts, ":"); + *ivopts = strsep(&tmp, "-"); + *ivmode = strsep(&*ivopts, ":"); if (tmp) DMWARN("Ignoring unexpected additional cipher options"); @@ -2313,12 +2380,12 @@ static int crypt_ctr_cipher(struct dm_target *ti, * For compatibility with the original dm-crypt mapping format, if * only the cipher name is supplied, use cbc-plain. */ - if (!chainmode || (!strcmp(chainmode, "plain") && !ivmode)) { + if (!chainmode || (!strcmp(chainmode, "plain") && !*ivmode)) { chainmode = "cbc"; - ivmode = "plain"; + *ivmode = "plain"; } - if (strcmp(chainmode, "ecb") && !ivmode) { + if (strcmp(chainmode, "ecb") && !*ivmode) { ti->error = "IV mechanism required"; return -EINVAL; } @@ -2338,19 +2405,45 @@ static int crypt_ctr_cipher(struct dm_target *ti, ret = crypt_alloc_tfms(cc, cipher_api); if (ret < 0) { ti->error = "Error allocating crypto tfm"; - goto bad; + kfree(cipher_api); + return ret; } + return 0; +bad_mem: + ti->error = "Cannot allocate cipher strings"; + return -ENOMEM; +} + +static int crypt_ctr_cipher(struct dm_target *ti, char *cipher_in, char *key) +{ + struct crypt_config *cc = ti->private; + char *ivmode = NULL, *ivopts = NULL; + int ret; + + cc->cipher_string = kstrdup(cipher_in, GFP_KERNEL); + if (!cc->cipher_string) { + ti->error = "Cannot allocate cipher strings"; + return -ENOMEM; + } + + if (strstarts(cipher_in, "capi:")) + ret = crypt_ctr_cipher_new(ti, cipher_in, key, &ivmode, &ivopts); + else + ret = crypt_ctr_cipher_old(ti, cipher_in, key, &ivmode, &ivopts); + if (ret) + return ret; + /* Initialize IV */ ret = crypt_ctr_ivmode(ti, ivmode); if (ret < 0) - goto bad; + return ret; /* Initialize and set key */ ret = crypt_set_key(cc, key); if (ret < 0) { ti->error = "Error decoding and setting key"; - goto bad; + return ret; } /* Allocate IV */ @@ -2358,7 +2451,7 @@ static int crypt_ctr_cipher(struct dm_target *ti, ret = cc->iv_gen_ops->ctr(cc, ti, ivopts); if (ret < 0) { ti->error = "Error creating IV"; - goto bad; + return ret; } } @@ -2367,18 +2460,11 @@ static int crypt_ctr_cipher(struct dm_target *ti, ret = cc->iv_gen_ops->init(cc); if (ret < 0) { ti->error = "Error initialising IV"; - goto bad; + return ret; } } - ret = 0; -bad: - kfree(cipher_api); return ret; - -bad_mem: - ti->error = "Cannot allocate cipher strings"; - return -ENOMEM; } static int crypt_ctr_optional(struct dm_target *ti, unsigned int argc, char **argv)