Received: by 2002:ab2:1149:0:b0:1f3:1f8c:d0c6 with SMTP id z9csp2538212lqz; Wed, 3 Apr 2024 00:24:05 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCWR5EJQmOHslFNPTcrAOeiTq+YQzvxbF4LPYFX+T80TCD3GUpyHdyn5fbElbpLPkSVGDzfQSeLR9JR/ZKC1vmQ5moL7Jzr3PRhXBo5JdQ== X-Google-Smtp-Source: AGHT+IHa3vN6273KZRJ+It9SRJu6KxCtJdO1qaNudeFSi+dN/386euF/XXDfLvJqNjKbuBVdVA9L X-Received: by 2002:a17:906:b84e:b0:a4e:988c:74cc with SMTP id ga14-20020a170906b84e00b00a4e988c74ccmr1452635ejb.11.1712129045115; Wed, 03 Apr 2024 00:24:05 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1712129045; cv=pass; d=google.com; s=arc-20160816; b=GjysAvoe20Mj5kxVS+7LBIB3KmNVzyW4VNOyrdtkIBn3JzYqXjEMuiU8bWI02DwdRd ae3+9dZ0bn4god+JWudA5y4t8GoSPYBxBNm+f/svz3N5ximIWs1mshB1Qz2AjQKKhQha Jfcn8bVbf1q16GVCIeg0Y+K4bpISTjRacy7h9UeZOSaxaDymF03N5rYIOVIXqF15D5lX orJxaHUoG1ExlioHGceRmEwm3eoou5oduqxXeSson/O9H3KvVhauP5icHfllNZ+K0rkx j0GtM7YPzYKzj8QPkopT64T5oD1m3uIH0UcfKcSoOmDQPTcVpv2zQQlGusr4ah64BYC/ LfJA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=Jk3bunkUZB3eJdbTI0pWomxdZHb/buVMZM8Xz7Iwzes=; fh=jgf3Iz0DIkrOUbFyEJLa/L48Mpm6Y0vTTudJA1ZdXN0=; b=AzwVk+XNyC1kRUp8thy0sEXTvIixXVnJRhFwhxR0F6lrqVVskMihDXlbo8O9aZWhei vP3er5GjC9utGjDD7BtYzfGOrr5isHykQ1+WE85PVg8iGxC6lVAuFPQ2uMAWy+pYAlDT sF+ktvYMNuGJJdlxX/Zp+GpIWvMF0IF1ltCgCcF73bD3B6QWApw8yIsoe6d5cAPfjMBi l4xySeT5NZ9pClwKgdKubMlbasevzn2GLFEiI40iXjfpJLTf/wjHZFmsSFEAR2srWYs6 AQF3W0dDBpEUAPk5PrsKkZ2Fsar89+YfUpw8kYszdiBJu687NG/YMVHTMJJ/cGz7G8+u 6R4Q==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@sigma-star.at header.s=google header.b=s9uLb9Gc; arc=pass (i=1 spf=pass spfdomain=sigma-star.at dkim=pass dkdomain=sigma-star.at dmarc=pass fromdomain=sigma-star.at); spf=pass (google.com: domain of linux-crypto+bounces-3274-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-crypto+bounces-3274-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=sigma-star.at Return-Path: Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [2604:1380:4601:e00::3]) by mx.google.com with ESMTPS id w23-20020a170906131700b00a4e84c116besi1646496ejb.414.2024.04.03.00.24.05 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Apr 2024 00:24:05 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-crypto+bounces-3274-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) client-ip=2604:1380:4601:e00::3; Authentication-Results: mx.google.com; dkim=pass header.i=@sigma-star.at header.s=google header.b=s9uLb9Gc; arc=pass (i=1 spf=pass spfdomain=sigma-star.at dkim=pass dkdomain=sigma-star.at dmarc=pass fromdomain=sigma-star.at); spf=pass (google.com: domain of linux-crypto+bounces-3274-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-crypto+bounces-3274-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=sigma-star.at Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by am.mirrors.kernel.org (Postfix) with ESMTPS id AE4A71F2420D for ; Wed, 3 Apr 2024 07:22:40 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id A995E67C44; Wed, 3 Apr 2024 07:21:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=sigma-star.at header.i=@sigma-star.at header.b="s9uLb9Gc" X-Original-To: linux-crypto@vger.kernel.org Received: from mail-lj1-f174.google.com (mail-lj1-f174.google.com [209.85.208.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DD5365D73D for ; Wed, 3 Apr 2024 07:21:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.174 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712128910; cv=none; b=sqgx8YPz0ZNQt/l26fyvTzh9t7Um6qdZ0CtQpxNSsEBWamtf3pu7YrpUGsah01tmK54sRsonpYwR3Dim+1+TxsaaNC1A/aG1lB60gVij5RKh+ZMgL1az24S6Mavz3bxg2Y12XDJ4WpcIqqskM/MEsP3/HRBR4pLJckjmw87B4Sc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712128910; c=relaxed/simple; bh=Xr7SHlqReVMUGU8MnJMNHJB/GT7lVWiG8UM22EKgLlw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ie2pdsGsdzZLRd2kEXRdW7LC0HpxRwReGqemQ1Xqh3YeYDbTz/Il3jMANnSa0PUOd04Ur/Pprf/aQAuBwf65wDdjvPeOSXP8f1bSCXxQTjU2J/cWIUqZ4eoHU39ttuqxIkY9miPW8M6kghmyohi25OJQ64z5K6FI7ECVUiwKoYU= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=sigma-star.at; spf=pass smtp.mailfrom=sigma-star.at; dkim=pass (2048-bit key) header.d=sigma-star.at header.i=@sigma-star.at header.b=s9uLb9Gc; arc=none smtp.client-ip=209.85.208.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=sigma-star.at Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=sigma-star.at Received: by mail-lj1-f174.google.com with SMTP id 38308e7fff4ca-2d717603aa5so63294741fa.0 for ; Wed, 03 Apr 2024 00:21:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sigma-star.at; s=google; t=1712128906; x=1712733706; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Jk3bunkUZB3eJdbTI0pWomxdZHb/buVMZM8Xz7Iwzes=; b=s9uLb9GcxCcLiJUyRuyhJIncOiYt0aZp5RINPTglNTt2W4/fZIjADvI94/KGOUMPuG AepbLWIT24tEFtS1ejx7Gomhi2TzkQlS+iPB1Xldz8I8YEgqU7MvfRnFhRXJJDw6JvyD 5niCyWObUQcBytlkNKXgT2hcCwD+zPLNWsHrb+x7NirfEgly8hKlCahc8LEh7G/R6zYF jaesCR4jStbOE25NyeaE8/YwyNduUodOnwFz5xletwML6Vsb1uHcMhOZPvHVnkZg6tPr Ea/LIufB+oZIWy6m+ioBevlKRHxNNt6PGft9lRl2qXvts/y3w5pSE0W/BAL6bUKlmoFe YXHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712128906; x=1712733706; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Jk3bunkUZB3eJdbTI0pWomxdZHb/buVMZM8Xz7Iwzes=; b=btnmIyeiKnpZbn32df+R67B81nAialgAMW2LoyQJtQzB4D852C2OB2uWFOOXssaqkk 7Gk/AsBgxe7AltN0HO2HvE8cdBYDkTwB3d3Y4osQZFUFNEPnAiWj++c7MGc9Z1q6QFcl yw9/xUbayorCrk4FJhFxcJG7b6TuE8vL7AtQEOJiKU2NJ/V4Lf+cVaoOpxwxNKQrOJ/a eHN7hQ41WopDk/uo+ycp/YyQkLFYDO60I+D4DAr5+pfllTJDs1dGh+V2YidRWx9vs4RK VOA1uKHA7CqHwUXyILyNlbVkieWpBaqbOIFblR04ptJkK9r4TgD5+zoPbYYymbc9nd58 BMWg== X-Forwarded-Encrypted: i=1; AJvYcCUBFMtA/LSEwKjlTO2aF/ZHhhQ6EhHIYVOxPeNtRWbT61ZoqoA+0L+5rMay47SrhMlTqLyF9hrfWQtHUu1lN80253H12v0ybSPYAGKp X-Gm-Message-State: AOJu0YyVW1KtzuuQ9acvle1aulc3IiWIJMYZ0qaVnfsQ6JNGOzfxVOsA GPllQiu7Yvh6nxwMyS5NMc+x8Zd0lM8joItC6+9Yrfm0e6HjvRD+7i0bz0i6Oq0= X-Received: by 2002:a2e:6a14:0:b0:2d6:8e88:5a6c with SMTP id f20-20020a2e6a14000000b002d68e885a6cmr9957510ljc.49.1712128906016; Wed, 03 Apr 2024 00:21:46 -0700 (PDT) Received: from localhost ([82.150.214.1]) by smtp.gmail.com with UTF8SMTPSA id p6-20020a05600c468600b0041477f3f99fsm23581891wmo.30.2024.04.03.00.21.44 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 03 Apr 2024 00:21:45 -0700 (PDT) From: David Gstir To: Mimi Zohar , James Bottomley , Jarkko Sakkinen , Herbert Xu , "David S. Miller" Cc: David Gstir , Shawn Guo , Jonathan Corbet , Sascha Hauer , Pengutronix Kernel Team , Fabio Estevam , NXP Linux Team , Ahmad Fatoum , sigma star Kernel Team , David Howells , Li Yang , Paul Moore , James Morris , "Serge E. Hallyn" , "Paul E. McKenney" , Randy Dunlap , Catalin Marinas , "Rafael J. Wysocki" , Tejun Heo , "Steven Rostedt (Google)" , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, keyrings@vger.kernel.org, linux-crypto@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linuxppc-dev@lists.ozlabs.org, linux-security-module@vger.kernel.org, Richard Weinberger , David Oberhollenzer Subject: [PATCH v8 3/6] KEYS: trusted: Introduce NXP DCP-backed trusted keys Date: Wed, 3 Apr 2024 09:21:19 +0200 Message-ID: <20240403072131.54935-4-david@sigma-star.at> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240403072131.54935-1-david@sigma-star.at> References: <20240403072131.54935-1-david@sigma-star.at> Precedence: bulk X-Mailing-List: linux-crypto@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit DCP (Data Co-Processor) is the little brother of NXP's CAAM IP. Beside of accelerated crypto operations, it also offers support for hardware-bound keys. Using this feature it is possible to implement a blob mechanism similar to what CAAM offers. Unlike on CAAM, constructing and parsing the blob has to happen in software (i.e. the kernel). The software-based blob format used by DCP trusted keys encrypts the payload using AES-128-GCM with a freshly generated random key and nonce. The random key itself is AES-128-ECB encrypted using the DCP unique or OTP key. The DCP trusted key blob format is: /* * struct dcp_blob_fmt - DCP BLOB format. * * @fmt_version: Format version, currently being %1 * @blob_key: Random AES 128 key which is used to encrypt @payload, * @blob_key itself is encrypted with OTP or UNIQUE device key in * AES-128-ECB mode by DCP. * @nonce: Random nonce used for @payload encryption. * @payload_len: Length of the plain text @payload. * @payload: The payload itself, encrypted using AES-128-GCM and @blob_key, * GCM auth tag of size AES_BLOCK_SIZE is attached at the end of it. * * The total size of a DCP BLOB is sizeof(struct dcp_blob_fmt) + @payload_len + * AES_BLOCK_SIZE. */ struct dcp_blob_fmt { __u8 fmt_version; __u8 blob_key[AES_KEYSIZE_128]; __u8 nonce[AES_KEYSIZE_128]; __le32 payload_len; __u8 payload[]; } __packed; By default the unique key is used. It is also possible to use the OTP key. While the unique key should be unique it is not documented how this key is derived. Therefore selection the OTP key is supported as well via the use_otp_key module parameter. Co-developed-by: Richard Weinberger Signed-off-by: Richard Weinberger Co-developed-by: David Oberhollenzer Signed-off-by: David Oberhollenzer Signed-off-by: David Gstir Reviewed-by: Jarkko Sakkinen --- include/keys/trusted_dcp.h | 11 + security/keys/trusted-keys/Kconfig | 8 + security/keys/trusted-keys/Makefile | 2 + security/keys/trusted-keys/trusted_core.c | 6 +- security/keys/trusted-keys/trusted_dcp.c | 313 ++++++++++++++++++++++ 5 files changed, 339 insertions(+), 1 deletion(-) create mode 100644 include/keys/trusted_dcp.h create mode 100644 security/keys/trusted-keys/trusted_dcp.c diff --git a/include/keys/trusted_dcp.h b/include/keys/trusted_dcp.h new file mode 100644 index 000000000000..9aaa42075b40 --- /dev/null +++ b/include/keys/trusted_dcp.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2021 sigma star gmbh + */ + +#ifndef TRUSTED_DCP_H +#define TRUSTED_DCP_H + +extern struct trusted_key_ops dcp_trusted_key_ops; + +#endif diff --git a/security/keys/trusted-keys/Kconfig b/security/keys/trusted-keys/Kconfig index 553dc117f385..1fb8aa001995 100644 --- a/security/keys/trusted-keys/Kconfig +++ b/security/keys/trusted-keys/Kconfig @@ -39,6 +39,14 @@ config TRUSTED_KEYS_CAAM Enable use of NXP's Cryptographic Accelerator and Assurance Module (CAAM) as trusted key backend. +config TRUSTED_KEYS_DCP + bool "DCP-based trusted keys" + depends on CRYPTO_DEV_MXS_DCP >= TRUSTED_KEYS + default y + select HAVE_TRUSTED_KEYS + help + Enable use of NXP's DCP (Data Co-Processor) as trusted key backend. + if !HAVE_TRUSTED_KEYS comment "No trust source selected!" endif diff --git a/security/keys/trusted-keys/Makefile b/security/keys/trusted-keys/Makefile index 735aa0bc08ef..f0f3b27f688b 100644 --- a/security/keys/trusted-keys/Makefile +++ b/security/keys/trusted-keys/Makefile @@ -14,3 +14,5 @@ trusted-$(CONFIG_TRUSTED_KEYS_TPM) += tpm2key.asn1.o trusted-$(CONFIG_TRUSTED_KEYS_TEE) += trusted_tee.o trusted-$(CONFIG_TRUSTED_KEYS_CAAM) += trusted_caam.o + +trusted-$(CONFIG_TRUSTED_KEYS_DCP) += trusted_dcp.o diff --git a/security/keys/trusted-keys/trusted_core.c b/security/keys/trusted-keys/trusted_core.c index fee1ab2c734d..5113aeae5628 100644 --- a/security/keys/trusted-keys/trusted_core.c +++ b/security/keys/trusted-keys/trusted_core.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -30,7 +31,7 @@ MODULE_PARM_DESC(rng, "Select trusted key RNG"); static char *trusted_key_source; module_param_named(source, trusted_key_source, charp, 0); -MODULE_PARM_DESC(source, "Select trusted keys source (tpm, tee or caam)"); +MODULE_PARM_DESC(source, "Select trusted keys source (tpm, tee, caam or dcp)"); static const struct trusted_key_source trusted_key_sources[] = { #if defined(CONFIG_TRUSTED_KEYS_TPM) @@ -42,6 +43,9 @@ static const struct trusted_key_source trusted_key_sources[] = { #if defined(CONFIG_TRUSTED_KEYS_CAAM) { "caam", &trusted_key_caam_ops }, #endif +#if defined(CONFIG_TRUSTED_KEYS_DCP) + { "dcp", &dcp_trusted_key_ops }, +#endif }; DEFINE_STATIC_CALL_NULL(trusted_key_seal, *trusted_key_sources[0].ops->seal); diff --git a/security/keys/trusted-keys/trusted_dcp.c b/security/keys/trusted-keys/trusted_dcp.c new file mode 100644 index 000000000000..16c44aafeab3 --- /dev/null +++ b/security/keys/trusted-keys/trusted_dcp.c @@ -0,0 +1,313 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2021 sigma star gmbh + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DCP_BLOB_VERSION 1 +#define DCP_BLOB_AUTHLEN 16 + +/** + * struct dcp_blob_fmt - DCP BLOB format. + * + * @fmt_version: Format version, currently being %1. + * @blob_key: Random AES 128 key which is used to encrypt @payload, + * @blob_key itself is encrypted with OTP or UNIQUE device key in + * AES-128-ECB mode by DCP. + * @nonce: Random nonce used for @payload encryption. + * @payload_len: Length of the plain text @payload. + * @payload: The payload itself, encrypted using AES-128-GCM and @blob_key, + * GCM auth tag of size DCP_BLOB_AUTHLEN is attached at the end of it. + * + * The total size of a DCP BLOB is sizeof(struct dcp_blob_fmt) + @payload_len + + * DCP_BLOB_AUTHLEN. + */ +struct dcp_blob_fmt { + __u8 fmt_version; + __u8 blob_key[AES_KEYSIZE_128]; + __u8 nonce[AES_KEYSIZE_128]; + __le32 payload_len; + __u8 payload[]; +} __packed; + +static bool use_otp_key; +module_param_named(dcp_use_otp_key, use_otp_key, bool, 0); +MODULE_PARM_DESC(dcp_use_otp_key, "Use OTP instead of UNIQUE key for sealing"); + +static bool skip_zk_test; +module_param_named(dcp_skip_zk_test, skip_zk_test, bool, 0); +MODULE_PARM_DESC(dcp_skip_zk_test, "Don't test whether device keys are zero'ed"); + +static unsigned int calc_blob_len(unsigned int payload_len) +{ + return sizeof(struct dcp_blob_fmt) + payload_len + DCP_BLOB_AUTHLEN; +} + +static int do_dcp_crypto(u8 *in, u8 *out, bool do_encrypt) +{ + struct skcipher_request *req = NULL; + struct scatterlist src_sg, dst_sg; + struct crypto_skcipher *tfm; + u8 paes_key[DCP_PAES_KEYSIZE]; + DECLARE_CRYPTO_WAIT(wait); + int res = 0; + + if (use_otp_key) + paes_key[0] = DCP_PAES_KEY_OTP; + else + paes_key[0] = DCP_PAES_KEY_UNIQUE; + + tfm = crypto_alloc_skcipher("ecb-paes-dcp", CRYPTO_ALG_INTERNAL, + CRYPTO_ALG_INTERNAL); + if (IS_ERR(tfm)) { + res = PTR_ERR(tfm); + tfm = NULL; + goto out; + } + + req = skcipher_request_alloc(tfm, GFP_NOFS); + if (!req) { + res = -ENOMEM; + goto out; + } + + skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP, + crypto_req_done, &wait); + res = crypto_skcipher_setkey(tfm, paes_key, sizeof(paes_key)); + if (res < 0) + goto out; + + sg_init_one(&src_sg, in, AES_KEYSIZE_128); + sg_init_one(&dst_sg, out, AES_KEYSIZE_128); + skcipher_request_set_crypt(req, &src_sg, &dst_sg, AES_KEYSIZE_128, + NULL); + + if (do_encrypt) + res = crypto_wait_req(crypto_skcipher_encrypt(req), &wait); + else + res = crypto_wait_req(crypto_skcipher_decrypt(req), &wait); + +out: + skcipher_request_free(req); + crypto_free_skcipher(tfm); + + return res; +} + +static int do_aead_crypto(u8 *in, u8 *out, size_t len, u8 *key, u8 *nonce, + bool do_encrypt) +{ + struct aead_request *aead_req = NULL; + struct scatterlist src_sg, dst_sg; + struct crypto_aead *aead; + int ret; + + aead = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(aead)) { + ret = PTR_ERR(aead); + goto out; + } + + ret = crypto_aead_setauthsize(aead, DCP_BLOB_AUTHLEN); + if (ret < 0) { + pr_err("Can't set crypto auth tag len: %d\n", ret); + goto free_aead; + } + + aead_req = aead_request_alloc(aead, GFP_KERNEL); + if (!aead_req) { + ret = -ENOMEM; + goto free_aead; + } + + sg_init_one(&src_sg, in, len); + if (do_encrypt) { + /* + * If we encrypt our buffer has extra space for the auth tag. + */ + sg_init_one(&dst_sg, out, len + DCP_BLOB_AUTHLEN); + } else { + sg_init_one(&dst_sg, out, len); + } + + aead_request_set_crypt(aead_req, &src_sg, &dst_sg, len, nonce); + aead_request_set_callback(aead_req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, + NULL); + aead_request_set_ad(aead_req, 0); + + if (crypto_aead_setkey(aead, key, AES_KEYSIZE_128)) { + pr_err("Can't set crypto AEAD key\n"); + ret = -EINVAL; + goto free_req; + } + + if (do_encrypt) + ret = crypto_aead_encrypt(aead_req); + else + ret = crypto_aead_decrypt(aead_req); + +free_req: + aead_request_free(aead_req); +free_aead: + crypto_free_aead(aead); +out: + return ret; +} + +static int decrypt_blob_key(u8 *key) +{ + return do_dcp_crypto(key, key, false); +} + +static int encrypt_blob_key(u8 *key) +{ + return do_dcp_crypto(key, key, true); +} + +static int trusted_dcp_seal(struct trusted_key_payload *p, char *datablob) +{ + struct dcp_blob_fmt *b = (struct dcp_blob_fmt *)p->blob; + int blen, ret; + + blen = calc_blob_len(p->key_len); + if (blen > MAX_BLOB_SIZE) + return -E2BIG; + + b->fmt_version = DCP_BLOB_VERSION; + get_random_bytes(b->nonce, AES_KEYSIZE_128); + get_random_bytes(b->blob_key, AES_KEYSIZE_128); + + ret = do_aead_crypto(p->key, b->payload, p->key_len, b->blob_key, + b->nonce, true); + if (ret) { + pr_err("Unable to encrypt blob payload: %i\n", ret); + return ret; + } + + ret = encrypt_blob_key(b->blob_key); + if (ret) { + pr_err("Unable to encrypt blob key: %i\n", ret); + return ret; + } + + b->payload_len = get_unaligned_le32(&p->key_len); + p->blob_len = blen; + return 0; +} + +static int trusted_dcp_unseal(struct trusted_key_payload *p, char *datablob) +{ + struct dcp_blob_fmt *b = (struct dcp_blob_fmt *)p->blob; + int blen, ret; + + if (b->fmt_version != DCP_BLOB_VERSION) { + pr_err("DCP blob has bad version: %i, expected %i\n", + b->fmt_version, DCP_BLOB_VERSION); + ret = -EINVAL; + goto out; + } + + p->key_len = le32_to_cpu(b->payload_len); + blen = calc_blob_len(p->key_len); + if (blen != p->blob_len) { + pr_err("DCP blob has bad length: %i != %i\n", blen, + p->blob_len); + ret = -EINVAL; + goto out; + } + + ret = decrypt_blob_key(b->blob_key); + if (ret) { + pr_err("Unable to decrypt blob key: %i\n", ret); + goto out; + } + + ret = do_aead_crypto(b->payload, p->key, p->key_len + DCP_BLOB_AUTHLEN, + b->blob_key, b->nonce, false); + if (ret) { + pr_err("Unwrap of DCP payload failed: %i\n", ret); + goto out; + } + + ret = 0; +out: + return ret; +} + +static int test_for_zero_key(void) +{ + /* + * Encrypting a plaintext of all 0x55 bytes will yield + * this ciphertext in case the DCP test key is used. + */ + static const u8 bad[] = {0x9a, 0xda, 0xe0, 0x54, 0xf6, 0x3d, 0xfa, 0xff, + 0x5e, 0xa1, 0x8e, 0x45, 0xed, 0xf6, 0xea, 0x6f}; + void *buf = NULL; + int ret = 0; + + if (skip_zk_test) + goto out; + + buf = kmalloc(AES_BLOCK_SIZE, GFP_KERNEL); + if (!buf) { + ret = -ENOMEM; + goto out; + } + + memset(buf, 0x55, AES_BLOCK_SIZE); + + ret = do_dcp_crypto(buf, buf, true); + if (ret) + goto out; + + if (memcmp(buf, bad, AES_BLOCK_SIZE) == 0) { + pr_warn("Device neither in secure nor trusted mode!\n"); + ret = -EINVAL; + } +out: + kfree(buf); + return ret; +} + +static int trusted_dcp_init(void) +{ + int ret; + + if (use_otp_key) + pr_info("Using DCP OTP key\n"); + + ret = test_for_zero_key(); + if (ret) { + pr_warn("Test for zero'ed keys failed: %i\n", ret); + + return -EINVAL; + } + + return register_key_type(&key_type_trusted); +} + +static void trusted_dcp_exit(void) +{ + unregister_key_type(&key_type_trusted); +} + +struct trusted_key_ops dcp_trusted_key_ops = { + .exit = trusted_dcp_exit, + .init = trusted_dcp_init, + .seal = trusted_dcp_seal, + .unseal = trusted_dcp_unseal, + .migratable = 0, +}; -- 2.35.3