18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Key Wrapping: RFC3394 / NIST SP800-38F 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2015, Stephan Mueller <smueller@chronox.de> 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 78c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions 88c2ecf20Sopenharmony_ci * are met: 98c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 108c2ecf20Sopenharmony_ci * notice, and the entire permission notice in its entirety, 118c2ecf20Sopenharmony_ci * including the disclaimer of warranties. 128c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright 138c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer in the 148c2ecf20Sopenharmony_ci * documentation and/or other materials provided with the distribution. 158c2ecf20Sopenharmony_ci * 3. The name of the author may not be used to endorse or promote 168c2ecf20Sopenharmony_ci * products derived from this software without specific prior 178c2ecf20Sopenharmony_ci * written permission. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * ALTERNATIVELY, this product may be distributed under the terms of 208c2ecf20Sopenharmony_ci * the GNU General Public License, in which case the provisions of the GPL2 218c2ecf20Sopenharmony_ci * are required INSTEAD OF the above restrictions. (This clause is 228c2ecf20Sopenharmony_ci * necessary due to a potential bad interaction between the GPL and 238c2ecf20Sopenharmony_ci * the restrictions contained in a BSD-style copyright.) 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 268c2ecf20Sopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 278c2ecf20Sopenharmony_ci * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF 288c2ecf20Sopenharmony_ci * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 298c2ecf20Sopenharmony_ci * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 308c2ecf20Sopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 318c2ecf20Sopenharmony_ci * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 328c2ecf20Sopenharmony_ci * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 338c2ecf20Sopenharmony_ci * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 348c2ecf20Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 358c2ecf20Sopenharmony_ci * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH 368c2ecf20Sopenharmony_ci * DAMAGE. 378c2ecf20Sopenharmony_ci */ 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci/* 408c2ecf20Sopenharmony_ci * Note for using key wrapping: 418c2ecf20Sopenharmony_ci * 428c2ecf20Sopenharmony_ci * * The result of the encryption operation is the ciphertext starting 438c2ecf20Sopenharmony_ci * with the 2nd semiblock. The first semiblock is provided as the IV. 448c2ecf20Sopenharmony_ci * The IV used to start the encryption operation is the default IV. 458c2ecf20Sopenharmony_ci * 468c2ecf20Sopenharmony_ci * * The input for the decryption is the first semiblock handed in as an 478c2ecf20Sopenharmony_ci * IV. The ciphertext is the data starting with the 2nd semiblock. The 488c2ecf20Sopenharmony_ci * return code of the decryption operation will be EBADMSG in case an 498c2ecf20Sopenharmony_ci * integrity error occurs. 508c2ecf20Sopenharmony_ci * 518c2ecf20Sopenharmony_ci * To obtain the full result of an encryption as expected by SP800-38F, the 528c2ecf20Sopenharmony_ci * caller must allocate a buffer of plaintext + 8 bytes: 538c2ecf20Sopenharmony_ci * 548c2ecf20Sopenharmony_ci * unsigned int datalen = ptlen + crypto_skcipher_ivsize(tfm); 558c2ecf20Sopenharmony_ci * u8 data[datalen]; 568c2ecf20Sopenharmony_ci * u8 *iv = data; 578c2ecf20Sopenharmony_ci * u8 *pt = data + crypto_skcipher_ivsize(tfm); 588c2ecf20Sopenharmony_ci * <ensure that pt contains the plaintext of size ptlen> 598c2ecf20Sopenharmony_ci * sg_init_one(&sg, pt, ptlen); 608c2ecf20Sopenharmony_ci * skcipher_request_set_crypt(req, &sg, &sg, ptlen, iv); 618c2ecf20Sopenharmony_ci * 628c2ecf20Sopenharmony_ci * ==> After encryption, data now contains full KW result as per SP800-38F. 638c2ecf20Sopenharmony_ci * 648c2ecf20Sopenharmony_ci * In case of decryption, ciphertext now already has the expected length 658c2ecf20Sopenharmony_ci * and must be segmented appropriately: 668c2ecf20Sopenharmony_ci * 678c2ecf20Sopenharmony_ci * unsigned int datalen = CTLEN; 688c2ecf20Sopenharmony_ci * u8 data[datalen]; 698c2ecf20Sopenharmony_ci * <ensure that data contains full ciphertext> 708c2ecf20Sopenharmony_ci * u8 *iv = data; 718c2ecf20Sopenharmony_ci * u8 *ct = data + crypto_skcipher_ivsize(tfm); 728c2ecf20Sopenharmony_ci * unsigned int ctlen = datalen - crypto_skcipher_ivsize(tfm); 738c2ecf20Sopenharmony_ci * sg_init_one(&sg, ct, ctlen); 748c2ecf20Sopenharmony_ci * skcipher_request_set_crypt(req, &sg, &sg, ctlen, iv); 758c2ecf20Sopenharmony_ci * 768c2ecf20Sopenharmony_ci * ==> After decryption (which hopefully does not return EBADMSG), the ct 778c2ecf20Sopenharmony_ci * pointer now points to the plaintext of size ctlen. 788c2ecf20Sopenharmony_ci * 798c2ecf20Sopenharmony_ci * Note 2: KWP is not implemented as this would defy in-place operation. 808c2ecf20Sopenharmony_ci * If somebody wants to wrap non-aligned data, he should simply pad 818c2ecf20Sopenharmony_ci * the input with zeros to fill it up to the 8 byte boundary. 828c2ecf20Sopenharmony_ci */ 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci#include <linux/module.h> 858c2ecf20Sopenharmony_ci#include <linux/crypto.h> 868c2ecf20Sopenharmony_ci#include <linux/scatterlist.h> 878c2ecf20Sopenharmony_ci#include <crypto/scatterwalk.h> 888c2ecf20Sopenharmony_ci#include <crypto/internal/skcipher.h> 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistruct crypto_kw_block { 918c2ecf20Sopenharmony_ci#define SEMIBSIZE 8 928c2ecf20Sopenharmony_ci __be64 A; 938c2ecf20Sopenharmony_ci __be64 R; 948c2ecf20Sopenharmony_ci}; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci/* 978c2ecf20Sopenharmony_ci * Fast forward the SGL to the "end" length minus SEMIBSIZE. 988c2ecf20Sopenharmony_ci * The start in the SGL defined by the fast-forward is returned with 998c2ecf20Sopenharmony_ci * the walk variable 1008c2ecf20Sopenharmony_ci */ 1018c2ecf20Sopenharmony_cistatic void crypto_kw_scatterlist_ff(struct scatter_walk *walk, 1028c2ecf20Sopenharmony_ci struct scatterlist *sg, 1038c2ecf20Sopenharmony_ci unsigned int end) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci unsigned int skip = 0; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci /* The caller should only operate on full SEMIBLOCKs. */ 1088c2ecf20Sopenharmony_ci BUG_ON(end < SEMIBSIZE); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci skip = end - SEMIBSIZE; 1118c2ecf20Sopenharmony_ci while (sg) { 1128c2ecf20Sopenharmony_ci if (sg->length > skip) { 1138c2ecf20Sopenharmony_ci scatterwalk_start(walk, sg); 1148c2ecf20Sopenharmony_ci scatterwalk_advance(walk, skip); 1158c2ecf20Sopenharmony_ci break; 1168c2ecf20Sopenharmony_ci } else 1178c2ecf20Sopenharmony_ci skip -= sg->length; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci sg = sg_next(sg); 1208c2ecf20Sopenharmony_ci } 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic int crypto_kw_decrypt(struct skcipher_request *req) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 1268c2ecf20Sopenharmony_ci struct crypto_cipher *cipher = skcipher_cipher_simple(tfm); 1278c2ecf20Sopenharmony_ci struct crypto_kw_block block; 1288c2ecf20Sopenharmony_ci struct scatterlist *src, *dst; 1298c2ecf20Sopenharmony_ci u64 t = 6 * ((req->cryptlen) >> 3); 1308c2ecf20Sopenharmony_ci unsigned int i; 1318c2ecf20Sopenharmony_ci int ret = 0; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci /* 1348c2ecf20Sopenharmony_ci * Require at least 2 semiblocks (note, the 3rd semiblock that is 1358c2ecf20Sopenharmony_ci * required by SP800-38F is the IV. 1368c2ecf20Sopenharmony_ci */ 1378c2ecf20Sopenharmony_ci if (req->cryptlen < (2 * SEMIBSIZE) || req->cryptlen % SEMIBSIZE) 1388c2ecf20Sopenharmony_ci return -EINVAL; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci /* Place the IV into block A */ 1418c2ecf20Sopenharmony_ci memcpy(&block.A, req->iv, SEMIBSIZE); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci /* 1448c2ecf20Sopenharmony_ci * src scatterlist is read-only. dst scatterlist is r/w. During the 1458c2ecf20Sopenharmony_ci * first loop, src points to req->src and dst to req->dst. For any 1468c2ecf20Sopenharmony_ci * subsequent round, the code operates on req->dst only. 1478c2ecf20Sopenharmony_ci */ 1488c2ecf20Sopenharmony_ci src = req->src; 1498c2ecf20Sopenharmony_ci dst = req->dst; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci for (i = 0; i < 6; i++) { 1528c2ecf20Sopenharmony_ci struct scatter_walk src_walk, dst_walk; 1538c2ecf20Sopenharmony_ci unsigned int nbytes = req->cryptlen; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci while (nbytes) { 1568c2ecf20Sopenharmony_ci /* move pointer by nbytes in the SGL */ 1578c2ecf20Sopenharmony_ci crypto_kw_scatterlist_ff(&src_walk, src, nbytes); 1588c2ecf20Sopenharmony_ci /* get the source block */ 1598c2ecf20Sopenharmony_ci scatterwalk_copychunks(&block.R, &src_walk, SEMIBSIZE, 1608c2ecf20Sopenharmony_ci false); 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci /* perform KW operation: modify IV with counter */ 1638c2ecf20Sopenharmony_ci block.A ^= cpu_to_be64(t); 1648c2ecf20Sopenharmony_ci t--; 1658c2ecf20Sopenharmony_ci /* perform KW operation: decrypt block */ 1668c2ecf20Sopenharmony_ci crypto_cipher_decrypt_one(cipher, (u8 *)&block, 1678c2ecf20Sopenharmony_ci (u8 *)&block); 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci /* move pointer by nbytes in the SGL */ 1708c2ecf20Sopenharmony_ci crypto_kw_scatterlist_ff(&dst_walk, dst, nbytes); 1718c2ecf20Sopenharmony_ci /* Copy block->R into place */ 1728c2ecf20Sopenharmony_ci scatterwalk_copychunks(&block.R, &dst_walk, SEMIBSIZE, 1738c2ecf20Sopenharmony_ci true); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci nbytes -= SEMIBSIZE; 1768c2ecf20Sopenharmony_ci } 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci /* we now start to operate on the dst SGL only */ 1798c2ecf20Sopenharmony_ci src = req->dst; 1808c2ecf20Sopenharmony_ci dst = req->dst; 1818c2ecf20Sopenharmony_ci } 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci /* Perform authentication check */ 1848c2ecf20Sopenharmony_ci if (block.A != cpu_to_be64(0xa6a6a6a6a6a6a6a6ULL)) 1858c2ecf20Sopenharmony_ci ret = -EBADMSG; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci memzero_explicit(&block, sizeof(struct crypto_kw_block)); 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci return ret; 1908c2ecf20Sopenharmony_ci} 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_cistatic int crypto_kw_encrypt(struct skcipher_request *req) 1938c2ecf20Sopenharmony_ci{ 1948c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 1958c2ecf20Sopenharmony_ci struct crypto_cipher *cipher = skcipher_cipher_simple(tfm); 1968c2ecf20Sopenharmony_ci struct crypto_kw_block block; 1978c2ecf20Sopenharmony_ci struct scatterlist *src, *dst; 1988c2ecf20Sopenharmony_ci u64 t = 1; 1998c2ecf20Sopenharmony_ci unsigned int i; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci /* 2028c2ecf20Sopenharmony_ci * Require at least 2 semiblocks (note, the 3rd semiblock that is 2038c2ecf20Sopenharmony_ci * required by SP800-38F is the IV that occupies the first semiblock. 2048c2ecf20Sopenharmony_ci * This means that the dst memory must be one semiblock larger than src. 2058c2ecf20Sopenharmony_ci * Also ensure that the given data is aligned to semiblock. 2068c2ecf20Sopenharmony_ci */ 2078c2ecf20Sopenharmony_ci if (req->cryptlen < (2 * SEMIBSIZE) || req->cryptlen % SEMIBSIZE) 2088c2ecf20Sopenharmony_ci return -EINVAL; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci /* 2118c2ecf20Sopenharmony_ci * Place the predefined IV into block A -- for encrypt, the caller 2128c2ecf20Sopenharmony_ci * does not need to provide an IV, but he needs to fetch the final IV. 2138c2ecf20Sopenharmony_ci */ 2148c2ecf20Sopenharmony_ci block.A = cpu_to_be64(0xa6a6a6a6a6a6a6a6ULL); 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci /* 2178c2ecf20Sopenharmony_ci * src scatterlist is read-only. dst scatterlist is r/w. During the 2188c2ecf20Sopenharmony_ci * first loop, src points to req->src and dst to req->dst. For any 2198c2ecf20Sopenharmony_ci * subsequent round, the code operates on req->dst only. 2208c2ecf20Sopenharmony_ci */ 2218c2ecf20Sopenharmony_ci src = req->src; 2228c2ecf20Sopenharmony_ci dst = req->dst; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci for (i = 0; i < 6; i++) { 2258c2ecf20Sopenharmony_ci struct scatter_walk src_walk, dst_walk; 2268c2ecf20Sopenharmony_ci unsigned int nbytes = req->cryptlen; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci scatterwalk_start(&src_walk, src); 2298c2ecf20Sopenharmony_ci scatterwalk_start(&dst_walk, dst); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci while (nbytes) { 2328c2ecf20Sopenharmony_ci /* get the source block */ 2338c2ecf20Sopenharmony_ci scatterwalk_copychunks(&block.R, &src_walk, SEMIBSIZE, 2348c2ecf20Sopenharmony_ci false); 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci /* perform KW operation: encrypt block */ 2378c2ecf20Sopenharmony_ci crypto_cipher_encrypt_one(cipher, (u8 *)&block, 2388c2ecf20Sopenharmony_ci (u8 *)&block); 2398c2ecf20Sopenharmony_ci /* perform KW operation: modify IV with counter */ 2408c2ecf20Sopenharmony_ci block.A ^= cpu_to_be64(t); 2418c2ecf20Sopenharmony_ci t++; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci /* Copy block->R into place */ 2448c2ecf20Sopenharmony_ci scatterwalk_copychunks(&block.R, &dst_walk, SEMIBSIZE, 2458c2ecf20Sopenharmony_ci true); 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci nbytes -= SEMIBSIZE; 2488c2ecf20Sopenharmony_ci } 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci /* we now start to operate on the dst SGL only */ 2518c2ecf20Sopenharmony_ci src = req->dst; 2528c2ecf20Sopenharmony_ci dst = req->dst; 2538c2ecf20Sopenharmony_ci } 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci /* establish the IV for the caller to pick up */ 2568c2ecf20Sopenharmony_ci memcpy(req->iv, &block.A, SEMIBSIZE); 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci memzero_explicit(&block, sizeof(struct crypto_kw_block)); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci return 0; 2618c2ecf20Sopenharmony_ci} 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_cistatic int crypto_kw_create(struct crypto_template *tmpl, struct rtattr **tb) 2648c2ecf20Sopenharmony_ci{ 2658c2ecf20Sopenharmony_ci struct skcipher_instance *inst; 2668c2ecf20Sopenharmony_ci struct crypto_alg *alg; 2678c2ecf20Sopenharmony_ci int err; 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci inst = skcipher_alloc_instance_simple(tmpl, tb); 2708c2ecf20Sopenharmony_ci if (IS_ERR(inst)) 2718c2ecf20Sopenharmony_ci return PTR_ERR(inst); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci alg = skcipher_ialg_simple(inst); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci err = -EINVAL; 2768c2ecf20Sopenharmony_ci /* Section 5.1 requirement for KW */ 2778c2ecf20Sopenharmony_ci if (alg->cra_blocksize != sizeof(struct crypto_kw_block)) 2788c2ecf20Sopenharmony_ci goto out_free_inst; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci inst->alg.base.cra_blocksize = SEMIBSIZE; 2818c2ecf20Sopenharmony_ci inst->alg.base.cra_alignmask = 0; 2828c2ecf20Sopenharmony_ci inst->alg.ivsize = SEMIBSIZE; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci inst->alg.encrypt = crypto_kw_encrypt; 2858c2ecf20Sopenharmony_ci inst->alg.decrypt = crypto_kw_decrypt; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci err = skcipher_register_instance(tmpl, inst); 2888c2ecf20Sopenharmony_ci if (err) { 2898c2ecf20Sopenharmony_ciout_free_inst: 2908c2ecf20Sopenharmony_ci inst->free(inst); 2918c2ecf20Sopenharmony_ci } 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci return err; 2948c2ecf20Sopenharmony_ci} 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_cistatic struct crypto_template crypto_kw_tmpl = { 2978c2ecf20Sopenharmony_ci .name = "kw", 2988c2ecf20Sopenharmony_ci .create = crypto_kw_create, 2998c2ecf20Sopenharmony_ci .module = THIS_MODULE, 3008c2ecf20Sopenharmony_ci}; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cistatic int __init crypto_kw_init(void) 3038c2ecf20Sopenharmony_ci{ 3048c2ecf20Sopenharmony_ci return crypto_register_template(&crypto_kw_tmpl); 3058c2ecf20Sopenharmony_ci} 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_cistatic void __exit crypto_kw_exit(void) 3088c2ecf20Sopenharmony_ci{ 3098c2ecf20Sopenharmony_ci crypto_unregister_template(&crypto_kw_tmpl); 3108c2ecf20Sopenharmony_ci} 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_cisubsys_initcall(crypto_kw_init); 3138c2ecf20Sopenharmony_cimodule_exit(crypto_kw_exit); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL"); 3168c2ecf20Sopenharmony_ciMODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>"); 3178c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Key Wrapping (RFC3394 / NIST SP800-38F)"); 3188c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("kw"); 319