162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Key Wrapping: RFC3394 / NIST SP800-38F
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (C) 2015, Stephan Mueller <smueller@chronox.de>
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
762306a36Sopenharmony_ci * modification, are permitted provided that the following conditions
862306a36Sopenharmony_ci * are met:
962306a36Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright
1062306a36Sopenharmony_ci *    notice, and the entire permission notice in its entirety,
1162306a36Sopenharmony_ci *    including the disclaimer of warranties.
1262306a36Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright
1362306a36Sopenharmony_ci *    notice, this list of conditions and the following disclaimer in the
1462306a36Sopenharmony_ci *    documentation and/or other materials provided with the distribution.
1562306a36Sopenharmony_ci * 3. The name of the author may not be used to endorse or promote
1662306a36Sopenharmony_ci *    products derived from this software without specific prior
1762306a36Sopenharmony_ci *    written permission.
1862306a36Sopenharmony_ci *
1962306a36Sopenharmony_ci * ALTERNATIVELY, this product may be distributed under the terms of
2062306a36Sopenharmony_ci * the GNU General Public License, in which case the provisions of the GPL2
2162306a36Sopenharmony_ci * are required INSTEAD OF the above restrictions.  (This clause is
2262306a36Sopenharmony_ci * necessary due to a potential bad interaction between the GPL and
2362306a36Sopenharmony_ci * the restrictions contained in a BSD-style copyright.)
2462306a36Sopenharmony_ci *
2562306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
2662306a36Sopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2762306a36Sopenharmony_ci * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
2862306a36Sopenharmony_ci * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
2962306a36Sopenharmony_ci * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
3062306a36Sopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
3162306a36Sopenharmony_ci * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
3262306a36Sopenharmony_ci * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3362306a36Sopenharmony_ci * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3462306a36Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
3562306a36Sopenharmony_ci * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
3662306a36Sopenharmony_ci * DAMAGE.
3762306a36Sopenharmony_ci */
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci/*
4062306a36Sopenharmony_ci * Note for using key wrapping:
4162306a36Sopenharmony_ci *
4262306a36Sopenharmony_ci *	* The result of the encryption operation is the ciphertext starting
4362306a36Sopenharmony_ci *	  with the 2nd semiblock. The first semiblock is provided as the IV.
4462306a36Sopenharmony_ci *	  The IV used to start the encryption operation is the default IV.
4562306a36Sopenharmony_ci *
4662306a36Sopenharmony_ci *	* The input for the decryption is the first semiblock handed in as an
4762306a36Sopenharmony_ci *	  IV. The ciphertext is the data starting with the 2nd semiblock. The
4862306a36Sopenharmony_ci *	  return code of the decryption operation will be EBADMSG in case an
4962306a36Sopenharmony_ci *	  integrity error occurs.
5062306a36Sopenharmony_ci *
5162306a36Sopenharmony_ci * To obtain the full result of an encryption as expected by SP800-38F, the
5262306a36Sopenharmony_ci * caller must allocate a buffer of plaintext + 8 bytes:
5362306a36Sopenharmony_ci *
5462306a36Sopenharmony_ci *	unsigned int datalen = ptlen + crypto_skcipher_ivsize(tfm);
5562306a36Sopenharmony_ci *	u8 data[datalen];
5662306a36Sopenharmony_ci *	u8 *iv = data;
5762306a36Sopenharmony_ci *	u8 *pt = data + crypto_skcipher_ivsize(tfm);
5862306a36Sopenharmony_ci *		<ensure that pt contains the plaintext of size ptlen>
5962306a36Sopenharmony_ci *	sg_init_one(&sg, pt, ptlen);
6062306a36Sopenharmony_ci *	skcipher_request_set_crypt(req, &sg, &sg, ptlen, iv);
6162306a36Sopenharmony_ci *
6262306a36Sopenharmony_ci *	==> After encryption, data now contains full KW result as per SP800-38F.
6362306a36Sopenharmony_ci *
6462306a36Sopenharmony_ci * In case of decryption, ciphertext now already has the expected length
6562306a36Sopenharmony_ci * and must be segmented appropriately:
6662306a36Sopenharmony_ci *
6762306a36Sopenharmony_ci *	unsigned int datalen = CTLEN;
6862306a36Sopenharmony_ci *	u8 data[datalen];
6962306a36Sopenharmony_ci *		<ensure that data contains full ciphertext>
7062306a36Sopenharmony_ci *	u8 *iv = data;
7162306a36Sopenharmony_ci *	u8 *ct = data + crypto_skcipher_ivsize(tfm);
7262306a36Sopenharmony_ci *	unsigned int ctlen = datalen - crypto_skcipher_ivsize(tfm);
7362306a36Sopenharmony_ci *	sg_init_one(&sg, ct, ctlen);
7462306a36Sopenharmony_ci *	skcipher_request_set_crypt(req, &sg, &sg, ctlen, iv);
7562306a36Sopenharmony_ci *
7662306a36Sopenharmony_ci *	==> After decryption (which hopefully does not return EBADMSG), the ct
7762306a36Sopenharmony_ci *	pointer now points to the plaintext of size ctlen.
7862306a36Sopenharmony_ci *
7962306a36Sopenharmony_ci * Note 2: KWP is not implemented as this would defy in-place operation.
8062306a36Sopenharmony_ci *	   If somebody wants to wrap non-aligned data, he should simply pad
8162306a36Sopenharmony_ci *	   the input with zeros to fill it up to the 8 byte boundary.
8262306a36Sopenharmony_ci */
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci#include <linux/module.h>
8562306a36Sopenharmony_ci#include <linux/crypto.h>
8662306a36Sopenharmony_ci#include <linux/scatterlist.h>
8762306a36Sopenharmony_ci#include <crypto/scatterwalk.h>
8862306a36Sopenharmony_ci#include <crypto/internal/cipher.h>
8962306a36Sopenharmony_ci#include <crypto/internal/skcipher.h>
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_cistruct crypto_kw_block {
9262306a36Sopenharmony_ci#define SEMIBSIZE 8
9362306a36Sopenharmony_ci	__be64 A;
9462306a36Sopenharmony_ci	__be64 R;
9562306a36Sopenharmony_ci};
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci/*
9862306a36Sopenharmony_ci * Fast forward the SGL to the "end" length minus SEMIBSIZE.
9962306a36Sopenharmony_ci * The start in the SGL defined by the fast-forward is returned with
10062306a36Sopenharmony_ci * the walk variable
10162306a36Sopenharmony_ci */
10262306a36Sopenharmony_cistatic void crypto_kw_scatterlist_ff(struct scatter_walk *walk,
10362306a36Sopenharmony_ci				     struct scatterlist *sg,
10462306a36Sopenharmony_ci				     unsigned int end)
10562306a36Sopenharmony_ci{
10662306a36Sopenharmony_ci	unsigned int skip = 0;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	/* The caller should only operate on full SEMIBLOCKs. */
10962306a36Sopenharmony_ci	BUG_ON(end < SEMIBSIZE);
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	skip = end - SEMIBSIZE;
11262306a36Sopenharmony_ci	while (sg) {
11362306a36Sopenharmony_ci		if (sg->length > skip) {
11462306a36Sopenharmony_ci			scatterwalk_start(walk, sg);
11562306a36Sopenharmony_ci			scatterwalk_advance(walk, skip);
11662306a36Sopenharmony_ci			break;
11762306a36Sopenharmony_ci		}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci		skip -= sg->length;
12062306a36Sopenharmony_ci		sg = sg_next(sg);
12162306a36Sopenharmony_ci	}
12262306a36Sopenharmony_ci}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_cistatic int crypto_kw_decrypt(struct skcipher_request *req)
12562306a36Sopenharmony_ci{
12662306a36Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
12762306a36Sopenharmony_ci	struct crypto_cipher *cipher = skcipher_cipher_simple(tfm);
12862306a36Sopenharmony_ci	struct crypto_kw_block block;
12962306a36Sopenharmony_ci	struct scatterlist *src, *dst;
13062306a36Sopenharmony_ci	u64 t = 6 * ((req->cryptlen) >> 3);
13162306a36Sopenharmony_ci	unsigned int i;
13262306a36Sopenharmony_ci	int ret = 0;
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	/*
13562306a36Sopenharmony_ci	 * Require at least 2 semiblocks (note, the 3rd semiblock that is
13662306a36Sopenharmony_ci	 * required by SP800-38F is the IV.
13762306a36Sopenharmony_ci	 */
13862306a36Sopenharmony_ci	if (req->cryptlen < (2 * SEMIBSIZE) || req->cryptlen % SEMIBSIZE)
13962306a36Sopenharmony_ci		return -EINVAL;
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	/* Place the IV into block A */
14262306a36Sopenharmony_ci	memcpy(&block.A, req->iv, SEMIBSIZE);
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	/*
14562306a36Sopenharmony_ci	 * src scatterlist is read-only. dst scatterlist is r/w. During the
14662306a36Sopenharmony_ci	 * first loop, src points to req->src and dst to req->dst. For any
14762306a36Sopenharmony_ci	 * subsequent round, the code operates on req->dst only.
14862306a36Sopenharmony_ci	 */
14962306a36Sopenharmony_ci	src = req->src;
15062306a36Sopenharmony_ci	dst = req->dst;
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	for (i = 0; i < 6; i++) {
15362306a36Sopenharmony_ci		struct scatter_walk src_walk, dst_walk;
15462306a36Sopenharmony_ci		unsigned int nbytes = req->cryptlen;
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci		while (nbytes) {
15762306a36Sopenharmony_ci			/* move pointer by nbytes in the SGL */
15862306a36Sopenharmony_ci			crypto_kw_scatterlist_ff(&src_walk, src, nbytes);
15962306a36Sopenharmony_ci			/* get the source block */
16062306a36Sopenharmony_ci			scatterwalk_copychunks(&block.R, &src_walk, SEMIBSIZE,
16162306a36Sopenharmony_ci					       false);
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci			/* perform KW operation: modify IV with counter */
16462306a36Sopenharmony_ci			block.A ^= cpu_to_be64(t);
16562306a36Sopenharmony_ci			t--;
16662306a36Sopenharmony_ci			/* perform KW operation: decrypt block */
16762306a36Sopenharmony_ci			crypto_cipher_decrypt_one(cipher, (u8 *)&block,
16862306a36Sopenharmony_ci						  (u8 *)&block);
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci			/* move pointer by nbytes in the SGL */
17162306a36Sopenharmony_ci			crypto_kw_scatterlist_ff(&dst_walk, dst, nbytes);
17262306a36Sopenharmony_ci			/* Copy block->R into place */
17362306a36Sopenharmony_ci			scatterwalk_copychunks(&block.R, &dst_walk, SEMIBSIZE,
17462306a36Sopenharmony_ci					       true);
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci			nbytes -= SEMIBSIZE;
17762306a36Sopenharmony_ci		}
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci		/* we now start to operate on the dst SGL only */
18062306a36Sopenharmony_ci		src = req->dst;
18162306a36Sopenharmony_ci		dst = req->dst;
18262306a36Sopenharmony_ci	}
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	/* Perform authentication check */
18562306a36Sopenharmony_ci	if (block.A != cpu_to_be64(0xa6a6a6a6a6a6a6a6ULL))
18662306a36Sopenharmony_ci		ret = -EBADMSG;
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	memzero_explicit(&block, sizeof(struct crypto_kw_block));
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	return ret;
19162306a36Sopenharmony_ci}
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_cistatic int crypto_kw_encrypt(struct skcipher_request *req)
19462306a36Sopenharmony_ci{
19562306a36Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
19662306a36Sopenharmony_ci	struct crypto_cipher *cipher = skcipher_cipher_simple(tfm);
19762306a36Sopenharmony_ci	struct crypto_kw_block block;
19862306a36Sopenharmony_ci	struct scatterlist *src, *dst;
19962306a36Sopenharmony_ci	u64 t = 1;
20062306a36Sopenharmony_ci	unsigned int i;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	/*
20362306a36Sopenharmony_ci	 * Require at least 2 semiblocks (note, the 3rd semiblock that is
20462306a36Sopenharmony_ci	 * required by SP800-38F is the IV that occupies the first semiblock.
20562306a36Sopenharmony_ci	 * This means that the dst memory must be one semiblock larger than src.
20662306a36Sopenharmony_ci	 * Also ensure that the given data is aligned to semiblock.
20762306a36Sopenharmony_ci	 */
20862306a36Sopenharmony_ci	if (req->cryptlen < (2 * SEMIBSIZE) || req->cryptlen % SEMIBSIZE)
20962306a36Sopenharmony_ci		return -EINVAL;
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	/*
21262306a36Sopenharmony_ci	 * Place the predefined IV into block A -- for encrypt, the caller
21362306a36Sopenharmony_ci	 * does not need to provide an IV, but he needs to fetch the final IV.
21462306a36Sopenharmony_ci	 */
21562306a36Sopenharmony_ci	block.A = cpu_to_be64(0xa6a6a6a6a6a6a6a6ULL);
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	/*
21862306a36Sopenharmony_ci	 * src scatterlist is read-only. dst scatterlist is r/w. During the
21962306a36Sopenharmony_ci	 * first loop, src points to req->src and dst to req->dst. For any
22062306a36Sopenharmony_ci	 * subsequent round, the code operates on req->dst only.
22162306a36Sopenharmony_ci	 */
22262306a36Sopenharmony_ci	src = req->src;
22362306a36Sopenharmony_ci	dst = req->dst;
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	for (i = 0; i < 6; i++) {
22662306a36Sopenharmony_ci		struct scatter_walk src_walk, dst_walk;
22762306a36Sopenharmony_ci		unsigned int nbytes = req->cryptlen;
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci		scatterwalk_start(&src_walk, src);
23062306a36Sopenharmony_ci		scatterwalk_start(&dst_walk, dst);
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci		while (nbytes) {
23362306a36Sopenharmony_ci			/* get the source block */
23462306a36Sopenharmony_ci			scatterwalk_copychunks(&block.R, &src_walk, SEMIBSIZE,
23562306a36Sopenharmony_ci					       false);
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci			/* perform KW operation: encrypt block */
23862306a36Sopenharmony_ci			crypto_cipher_encrypt_one(cipher, (u8 *)&block,
23962306a36Sopenharmony_ci						  (u8 *)&block);
24062306a36Sopenharmony_ci			/* perform KW operation: modify IV with counter */
24162306a36Sopenharmony_ci			block.A ^= cpu_to_be64(t);
24262306a36Sopenharmony_ci			t++;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci			/* Copy block->R into place */
24562306a36Sopenharmony_ci			scatterwalk_copychunks(&block.R, &dst_walk, SEMIBSIZE,
24662306a36Sopenharmony_ci					       true);
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci			nbytes -= SEMIBSIZE;
24962306a36Sopenharmony_ci		}
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci		/* we now start to operate on the dst SGL only */
25262306a36Sopenharmony_ci		src = req->dst;
25362306a36Sopenharmony_ci		dst = req->dst;
25462306a36Sopenharmony_ci	}
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	/* establish the IV for the caller to pick up */
25762306a36Sopenharmony_ci	memcpy(req->iv, &block.A, SEMIBSIZE);
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	memzero_explicit(&block, sizeof(struct crypto_kw_block));
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	return 0;
26262306a36Sopenharmony_ci}
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_cistatic int crypto_kw_create(struct crypto_template *tmpl, struct rtattr **tb)
26562306a36Sopenharmony_ci{
26662306a36Sopenharmony_ci	struct skcipher_instance *inst;
26762306a36Sopenharmony_ci	struct crypto_alg *alg;
26862306a36Sopenharmony_ci	int err;
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	inst = skcipher_alloc_instance_simple(tmpl, tb);
27162306a36Sopenharmony_ci	if (IS_ERR(inst))
27262306a36Sopenharmony_ci		return PTR_ERR(inst);
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	alg = skcipher_ialg_simple(inst);
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	err = -EINVAL;
27762306a36Sopenharmony_ci	/* Section 5.1 requirement for KW */
27862306a36Sopenharmony_ci	if (alg->cra_blocksize != sizeof(struct crypto_kw_block))
27962306a36Sopenharmony_ci		goto out_free_inst;
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	inst->alg.base.cra_blocksize = SEMIBSIZE;
28262306a36Sopenharmony_ci	inst->alg.base.cra_alignmask = 0;
28362306a36Sopenharmony_ci	inst->alg.ivsize = SEMIBSIZE;
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	inst->alg.encrypt = crypto_kw_encrypt;
28662306a36Sopenharmony_ci	inst->alg.decrypt = crypto_kw_decrypt;
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	err = skcipher_register_instance(tmpl, inst);
28962306a36Sopenharmony_ci	if (err) {
29062306a36Sopenharmony_ciout_free_inst:
29162306a36Sopenharmony_ci		inst->free(inst);
29262306a36Sopenharmony_ci	}
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	return err;
29562306a36Sopenharmony_ci}
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_cistatic struct crypto_template crypto_kw_tmpl = {
29862306a36Sopenharmony_ci	.name = "kw",
29962306a36Sopenharmony_ci	.create = crypto_kw_create,
30062306a36Sopenharmony_ci	.module = THIS_MODULE,
30162306a36Sopenharmony_ci};
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_cistatic int __init crypto_kw_init(void)
30462306a36Sopenharmony_ci{
30562306a36Sopenharmony_ci	return crypto_register_template(&crypto_kw_tmpl);
30662306a36Sopenharmony_ci}
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_cistatic void __exit crypto_kw_exit(void)
30962306a36Sopenharmony_ci{
31062306a36Sopenharmony_ci	crypto_unregister_template(&crypto_kw_tmpl);
31162306a36Sopenharmony_ci}
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_cisubsys_initcall(crypto_kw_init);
31462306a36Sopenharmony_cimodule_exit(crypto_kw_exit);
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
31762306a36Sopenharmony_ciMODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
31862306a36Sopenharmony_ciMODULE_DESCRIPTION("Key Wrapping (RFC3394 / NIST SP800-38F)");
31962306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("kw");
32062306a36Sopenharmony_ciMODULE_IMPORT_NS(CRYPTO_INTERNAL);
321