158771c1cSSalvatore Benedetto /* 258771c1cSSalvatore Benedetto * ECDH helper functions - KPP wrappings 358771c1cSSalvatore Benedetto * 458771c1cSSalvatore Benedetto * Copyright (C) 2017 Intel Corporation 558771c1cSSalvatore Benedetto * 658771c1cSSalvatore Benedetto * This program is free software; you can redistribute it and/or modify 758771c1cSSalvatore Benedetto * it under the terms of the GNU General Public License version 2 as 858771c1cSSalvatore Benedetto * published by the Free Software Foundation; 958771c1cSSalvatore Benedetto * 1058771c1cSSalvatore Benedetto * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 1158771c1cSSalvatore Benedetto * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1258771c1cSSalvatore Benedetto * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 1358771c1cSSalvatore Benedetto * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 1458771c1cSSalvatore Benedetto * CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 1558771c1cSSalvatore Benedetto * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1658771c1cSSalvatore Benedetto * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1758771c1cSSalvatore Benedetto * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1858771c1cSSalvatore Benedetto * 1958771c1cSSalvatore Benedetto * ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 2058771c1cSSalvatore Benedetto * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 2158771c1cSSalvatore Benedetto * SOFTWARE IS DISCLAIMED. 2258771c1cSSalvatore Benedetto */ 2358771c1cSSalvatore Benedetto #include "ecdh_helper.h" 2458771c1cSSalvatore Benedetto 2558771c1cSSalvatore Benedetto #include <linux/scatterlist.h> 2658771c1cSSalvatore Benedetto #include <crypto/ecdh.h> 2758771c1cSSalvatore Benedetto 2858771c1cSSalvatore Benedetto static inline void swap_digits(u64 *in, u64 *out, unsigned int ndigits) 2958771c1cSSalvatore Benedetto { 3058771c1cSSalvatore Benedetto int i; 3158771c1cSSalvatore Benedetto 3258771c1cSSalvatore Benedetto for (i = 0; i < ndigits; i++) 3358771c1cSSalvatore Benedetto out[i] = __swab64(in[ndigits - 1 - i]); 3458771c1cSSalvatore Benedetto } 3558771c1cSSalvatore Benedetto 36c0153b0bSTudor Ambarus /* compute_ecdh_secret() - function assumes that the private key was 37c0153b0bSTudor Ambarus * already set. 38c0153b0bSTudor Ambarus * @tfm: KPP tfm handle allocated with crypto_alloc_kpp(). 39c0153b0bSTudor Ambarus * @public_key: pair's ecc public key. 40c0153b0bSTudor Ambarus * secret: memory where the ecdh computed shared secret will be saved. 41c0153b0bSTudor Ambarus * 42c0153b0bSTudor Ambarus * Return: zero on success; error code in case of error. 43c0153b0bSTudor Ambarus */ 44a2976416STudor Ambarus int compute_ecdh_secret(struct crypto_kpp *tfm, const u8 public_key[64], 45c0153b0bSTudor Ambarus u8 secret[32]) 4658771c1cSSalvatore Benedetto { 47*fe93d841SHerbert Xu DECLARE_CRYPTO_WAIT(result); 4858771c1cSSalvatore Benedetto struct kpp_request *req; 49c0153b0bSTudor Ambarus u8 *tmp; 5058771c1cSSalvatore Benedetto struct scatterlist src, dst; 51a2976416STudor Ambarus int err; 5258771c1cSSalvatore Benedetto 53763d9a30SSalvatore Benedetto tmp = kmalloc(64, GFP_KERNEL); 54763d9a30SSalvatore Benedetto if (!tmp) 55a2976416STudor Ambarus return -ENOMEM; 56763d9a30SSalvatore Benedetto 5758771c1cSSalvatore Benedetto req = kpp_request_alloc(tfm, GFP_KERNEL); 58a2976416STudor Ambarus if (!req) { 59a2976416STudor Ambarus err = -ENOMEM; 6047eb2ac8STudor Ambarus goto free_tmp; 61a2976416STudor Ambarus } 6258771c1cSSalvatore Benedetto 6358771c1cSSalvatore Benedetto swap_digits((u64 *)public_key, (u64 *)tmp, 4); /* x */ 6458771c1cSSalvatore Benedetto swap_digits((u64 *)&public_key[32], (u64 *)&tmp[32], 4); /* y */ 6558771c1cSSalvatore Benedetto 6658771c1cSSalvatore Benedetto sg_init_one(&src, tmp, 64); 6758771c1cSSalvatore Benedetto sg_init_one(&dst, secret, 32); 6858771c1cSSalvatore Benedetto kpp_request_set_input(req, &src, 64); 6958771c1cSSalvatore Benedetto kpp_request_set_output(req, &dst, 32); 7058771c1cSSalvatore Benedetto kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 71*fe93d841SHerbert Xu crypto_req_done, &result); 7258771c1cSSalvatore Benedetto err = crypto_kpp_compute_shared_secret(req); 73*fe93d841SHerbert Xu err = crypto_wait_req(err, &result); 7458771c1cSSalvatore Benedetto if (err < 0) { 7558771c1cSSalvatore Benedetto pr_err("alg: ecdh: compute shared secret failed. err %d\n", 7658771c1cSSalvatore Benedetto err); 7758771c1cSSalvatore Benedetto goto free_all; 7858771c1cSSalvatore Benedetto } 7958771c1cSSalvatore Benedetto 8058771c1cSSalvatore Benedetto swap_digits((u64 *)secret, (u64 *)tmp, 4); 8158771c1cSSalvatore Benedetto memcpy(secret, tmp, 32); 8258771c1cSSalvatore Benedetto 8358771c1cSSalvatore Benedetto free_all: 8458771c1cSSalvatore Benedetto kpp_request_free(req); 85763d9a30SSalvatore Benedetto free_tmp: 86453431a5SWaiman Long kfree_sensitive(tmp); 87a2976416STudor Ambarus return err; 8858771c1cSSalvatore Benedetto } 8958771c1cSSalvatore Benedetto 90c0153b0bSTudor Ambarus /* set_ecdh_privkey() - set or generate ecc private key. 91c0153b0bSTudor Ambarus * 92c0153b0bSTudor Ambarus * Function generates an ecc private key in the crypto subsystem when receiving 93c0153b0bSTudor Ambarus * a NULL private key or sets the received key when not NULL. 94c0153b0bSTudor Ambarus * 95c0153b0bSTudor Ambarus * @tfm: KPP tfm handle allocated with crypto_alloc_kpp(). 96c0153b0bSTudor Ambarus * @private_key: user's ecc private key. When not NULL, the key is expected 97c0153b0bSTudor Ambarus * in little endian format. 98c0153b0bSTudor Ambarus * 99c0153b0bSTudor Ambarus * Return: zero on success; error code in case of error. 100c0153b0bSTudor Ambarus */ 101c0153b0bSTudor Ambarus int set_ecdh_privkey(struct crypto_kpp *tfm, const u8 private_key[32]) 10258771c1cSSalvatore Benedetto { 103c0153b0bSTudor Ambarus u8 *buf, *tmp = NULL; 10458771c1cSSalvatore Benedetto unsigned int buf_len; 105a2976416STudor Ambarus int err; 106c0153b0bSTudor Ambarus struct ecdh p = {0}; 107c0153b0bSTudor Ambarus 108c0153b0bSTudor Ambarus if (private_key) { 109c0153b0bSTudor Ambarus tmp = kmalloc(32, GFP_KERNEL); 110c0153b0bSTudor Ambarus if (!tmp) 111c0153b0bSTudor Ambarus return -ENOMEM; 112c0153b0bSTudor Ambarus swap_digits((u64 *)private_key, (u64 *)tmp, 4); 113c0153b0bSTudor Ambarus p.key = tmp; 114c0153b0bSTudor Ambarus p.key_size = 32; 115c0153b0bSTudor Ambarus } 116c0153b0bSTudor Ambarus 117c0153b0bSTudor Ambarus buf_len = crypto_ecdh_key_len(&p); 118c0153b0bSTudor Ambarus buf = kmalloc(buf_len, GFP_KERNEL); 119c0153b0bSTudor Ambarus if (!buf) { 120c0153b0bSTudor Ambarus err = -ENOMEM; 121c0153b0bSTudor Ambarus goto free_tmp; 122c0153b0bSTudor Ambarus } 123c0153b0bSTudor Ambarus 124c0153b0bSTudor Ambarus err = crypto_ecdh_encode_key(buf, buf_len, &p); 125c0153b0bSTudor Ambarus if (err) 126c0153b0bSTudor Ambarus goto free_all; 127c0153b0bSTudor Ambarus 128c0153b0bSTudor Ambarus err = crypto_kpp_set_secret(tfm, buf, buf_len); 129c0153b0bSTudor Ambarus /* fall through */ 130c0153b0bSTudor Ambarus free_all: 131453431a5SWaiman Long kfree_sensitive(buf); 132c0153b0bSTudor Ambarus free_tmp: 133453431a5SWaiman Long kfree_sensitive(tmp); 134c0153b0bSTudor Ambarus return err; 135c0153b0bSTudor Ambarus } 136c0153b0bSTudor Ambarus 137c0153b0bSTudor Ambarus /* generate_ecdh_public_key() - function assumes that the private key was 138c0153b0bSTudor Ambarus * already set. 139c0153b0bSTudor Ambarus * 140c0153b0bSTudor Ambarus * @tfm: KPP tfm handle allocated with crypto_alloc_kpp(). 141c0153b0bSTudor Ambarus * @public_key: memory where the computed ecc public key will be saved. 142c0153b0bSTudor Ambarus * 143c0153b0bSTudor Ambarus * Return: zero on success; error code in case of error. 144c0153b0bSTudor Ambarus */ 145c0153b0bSTudor Ambarus int generate_ecdh_public_key(struct crypto_kpp *tfm, u8 public_key[64]) 146c0153b0bSTudor Ambarus { 147*fe93d841SHerbert Xu DECLARE_CRYPTO_WAIT(result); 148c0153b0bSTudor Ambarus struct kpp_request *req; 149c0153b0bSTudor Ambarus u8 *tmp; 150c0153b0bSTudor Ambarus struct scatterlist dst; 151c0153b0bSTudor Ambarus int err; 15258771c1cSSalvatore Benedetto 153763d9a30SSalvatore Benedetto tmp = kmalloc(64, GFP_KERNEL); 154763d9a30SSalvatore Benedetto if (!tmp) 155a2976416STudor Ambarus return -ENOMEM; 156763d9a30SSalvatore Benedetto 15758771c1cSSalvatore Benedetto req = kpp_request_alloc(tfm, GFP_KERNEL); 158a2976416STudor Ambarus if (!req) { 159a2976416STudor Ambarus err = -ENOMEM; 16047eb2ac8STudor Ambarus goto free_tmp; 161a2976416STudor Ambarus } 16258771c1cSSalvatore Benedetto 16358771c1cSSalvatore Benedetto sg_init_one(&dst, tmp, 64); 164f9583153SMarcel Holtmann kpp_request_set_input(req, NULL, 0); 16558771c1cSSalvatore Benedetto kpp_request_set_output(req, &dst, 64); 16658771c1cSSalvatore Benedetto kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 167*fe93d841SHerbert Xu crypto_req_done, &result); 16858771c1cSSalvatore Benedetto 16958771c1cSSalvatore Benedetto err = crypto_kpp_generate_public_key(req); 170*fe93d841SHerbert Xu err = crypto_wait_req(err, &result); 17158771c1cSSalvatore Benedetto if (err < 0) 17258771c1cSSalvatore Benedetto goto free_all; 17358771c1cSSalvatore Benedetto 174c0153b0bSTudor Ambarus /* The public key is handed back in little endian as expected by 175c0153b0bSTudor Ambarus * the Security Manager Protocol. 17658771c1cSSalvatore Benedetto */ 17758771c1cSSalvatore Benedetto swap_digits((u64 *)tmp, (u64 *)public_key, 4); /* x */ 17858771c1cSSalvatore Benedetto swap_digits((u64 *)&tmp[32], (u64 *)&public_key[32], 4); /* y */ 17958771c1cSSalvatore Benedetto 18058771c1cSSalvatore Benedetto free_all: 18158771c1cSSalvatore Benedetto kpp_request_free(req); 182763d9a30SSalvatore Benedetto free_tmp: 183763d9a30SSalvatore Benedetto kfree(tmp); 184a2976416STudor Ambarus return err; 18558771c1cSSalvatore Benedetto } 186c0153b0bSTudor Ambarus 187c0153b0bSTudor Ambarus /* generate_ecdh_keys() - generate ecc key pair. 188c0153b0bSTudor Ambarus * 189c0153b0bSTudor Ambarus * @tfm: KPP tfm handle allocated with crypto_alloc_kpp(). 190c0153b0bSTudor Ambarus * @public_key: memory where the computed ecc public key will be saved. 191c0153b0bSTudor Ambarus * 192c0153b0bSTudor Ambarus * Return: zero on success; error code in case of error. 193c0153b0bSTudor Ambarus */ 194c0153b0bSTudor Ambarus int generate_ecdh_keys(struct crypto_kpp *tfm, u8 public_key[64]) 195c0153b0bSTudor Ambarus { 196c0153b0bSTudor Ambarus int err; 197c0153b0bSTudor Ambarus 198c0153b0bSTudor Ambarus err = set_ecdh_privkey(tfm, NULL); 199c0153b0bSTudor Ambarus if (err) 200c0153b0bSTudor Ambarus return err; 201c0153b0bSTudor Ambarus 202c0153b0bSTudor Ambarus return generate_ecdh_public_key(tfm, public_key); 203c0153b0bSTudor Ambarus } 204